@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/dist/utils/config.js
CHANGED
|
@@ -190,6 +190,10 @@ export class CLIConfig {
|
|
|
190
190
|
}
|
|
191
191
|
// Enhanced Service Discovery Integration
|
|
192
192
|
async discoverServices(verbose = false) {
|
|
193
|
+
// Honour manually configured endpoints — skip auto-discovery so we don't clobber them.
|
|
194
|
+
if (this.config.manualEndpointOverrides) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
193
197
|
const isTestEnvironment = process.env.NODE_ENV === 'test';
|
|
194
198
|
const forceDiscovery = process.env.FORCE_SERVICE_DISCOVERY === 'true';
|
|
195
199
|
if ((isTestEnvironment && !forceDiscovery) || process.env.SKIP_SERVICE_DISCOVERY === 'true') {
|
|
@@ -434,6 +438,210 @@ export class CLIConfig {
|
|
|
434
438
|
}
|
|
435
439
|
throw new Error('Auth health endpoints unreachable');
|
|
436
440
|
}
|
|
441
|
+
getAuthVerificationEndpoints(pathname) {
|
|
442
|
+
const authBase = (this.config.discoveredServices?.auth_base || 'https://auth.lanonasis.com').replace(/\/$/, '');
|
|
443
|
+
return Array.from(new Set([
|
|
444
|
+
`${authBase}${pathname}`,
|
|
445
|
+
`https://auth.lanonasis.com${pathname}`,
|
|
446
|
+
`http://localhost:4000${pathname}`
|
|
447
|
+
]));
|
|
448
|
+
}
|
|
449
|
+
extractAuthErrorMessage(payload) {
|
|
450
|
+
if (!payload || typeof payload !== 'object') {
|
|
451
|
+
return undefined;
|
|
452
|
+
}
|
|
453
|
+
const data = payload;
|
|
454
|
+
const fields = ['message', 'error', 'reason', 'code'];
|
|
455
|
+
for (const field of fields) {
|
|
456
|
+
const value = data[field];
|
|
457
|
+
if (typeof value === 'string' && value.trim().length > 0) {
|
|
458
|
+
return value;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
return undefined;
|
|
462
|
+
}
|
|
463
|
+
async verifyTokenWithAuthGateway(token) {
|
|
464
|
+
const headers = {
|
|
465
|
+
'Authorization': `Bearer ${token}`,
|
|
466
|
+
'X-Project-Scope': 'lanonasis-maas'
|
|
467
|
+
};
|
|
468
|
+
let fallbackReason = 'Unable to verify token with auth gateway';
|
|
469
|
+
// Primary check (required by auth contract): /v1/auth/verify
|
|
470
|
+
for (const endpoint of this.getAuthVerificationEndpoints('/v1/auth/verify')) {
|
|
471
|
+
try {
|
|
472
|
+
const response = await axios.post(endpoint, {}, {
|
|
473
|
+
headers,
|
|
474
|
+
timeout: 5000,
|
|
475
|
+
proxy: false
|
|
476
|
+
});
|
|
477
|
+
const payload = response.data;
|
|
478
|
+
if (payload.valid === true || Boolean(payload.payload)) {
|
|
479
|
+
return { valid: true, method: 'token', endpoint };
|
|
480
|
+
}
|
|
481
|
+
if (payload.valid === false) {
|
|
482
|
+
return {
|
|
483
|
+
valid: false,
|
|
484
|
+
method: 'token',
|
|
485
|
+
endpoint,
|
|
486
|
+
reason: this.extractAuthErrorMessage(payload) || 'Token is invalid'
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
catch (error) {
|
|
491
|
+
const normalizedError = this.normalizeServiceError(error);
|
|
492
|
+
const responsePayload = normalizedError.response?.data;
|
|
493
|
+
const responseCode = typeof responsePayload?.code === 'string' ? responsePayload.code : undefined;
|
|
494
|
+
const reason = this.extractAuthErrorMessage(responsePayload) || normalizedError.message || fallbackReason;
|
|
495
|
+
fallbackReason = reason;
|
|
496
|
+
// If auth gateway explicitly rejected token, stop early.
|
|
497
|
+
if ((normalizedError.response?.status === 401 || normalizedError.response?.status === 403) &&
|
|
498
|
+
responseCode &&
|
|
499
|
+
responseCode !== 'AUTH_TOKEN_MISSING') {
|
|
500
|
+
return { valid: false, method: 'token', endpoint, reason };
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
// Fallback for deployments where proxy layers strip Authorization headers.
|
|
505
|
+
for (const endpoint of this.getAuthVerificationEndpoints('/v1/auth/verify-token')) {
|
|
506
|
+
try {
|
|
507
|
+
const response = await axios.post(endpoint, { token }, {
|
|
508
|
+
headers: {
|
|
509
|
+
'Content-Type': 'application/json',
|
|
510
|
+
'X-Project-Scope': 'lanonasis-maas'
|
|
511
|
+
},
|
|
512
|
+
timeout: 5000,
|
|
513
|
+
proxy: false
|
|
514
|
+
});
|
|
515
|
+
const payload = response.data;
|
|
516
|
+
if (payload.valid === true) {
|
|
517
|
+
return { valid: true, method: 'token', endpoint };
|
|
518
|
+
}
|
|
519
|
+
if (payload.valid === false) {
|
|
520
|
+
return {
|
|
521
|
+
valid: false,
|
|
522
|
+
method: 'token',
|
|
523
|
+
endpoint,
|
|
524
|
+
reason: this.extractAuthErrorMessage(payload) || 'Token is invalid'
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
catch (error) {
|
|
529
|
+
const normalizedError = this.normalizeServiceError(error);
|
|
530
|
+
const responsePayload = normalizedError.response?.data;
|
|
531
|
+
fallbackReason = this.extractAuthErrorMessage(responsePayload) || normalizedError.message || fallbackReason;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
return {
|
|
535
|
+
valid: false,
|
|
536
|
+
method: 'token',
|
|
537
|
+
reason: fallbackReason
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
async verifyVendorKeyWithAuthGateway(vendorKey) {
|
|
541
|
+
// Detect whether the stored "vendor key" is actually an OAuth/JWT access token
|
|
542
|
+
// (3-part base64url string separated by dots). OAuth tokens must be verified via the
|
|
543
|
+
// Bearer token path (/v1/auth/verify-token), not as API keys (/v1/auth/verify-api-key),
|
|
544
|
+
// because they are not stored in the api_keys table.
|
|
545
|
+
const isJwtFormat = /^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(vendorKey.trim());
|
|
546
|
+
if (isJwtFormat) {
|
|
547
|
+
// Delegate to token verification — the auth gateway's UAI router accepts Bearer tokens
|
|
548
|
+
// on /v1/auth/verify (requireAuth) and /v1/auth/verify-token (public, body-based).
|
|
549
|
+
return this.verifyTokenWithAuthGateway(vendorKey);
|
|
550
|
+
}
|
|
551
|
+
const headers = {
|
|
552
|
+
'X-API-Key': vendorKey,
|
|
553
|
+
'X-Auth-Method': 'vendor_key',
|
|
554
|
+
'X-Project-Scope': 'lanonasis-maas'
|
|
555
|
+
};
|
|
556
|
+
let fallbackReason = 'Unable to verify API key with auth gateway';
|
|
557
|
+
// Primary check (required by auth contract): /v1/auth/verify
|
|
558
|
+
for (const endpoint of this.getAuthVerificationEndpoints('/v1/auth/verify')) {
|
|
559
|
+
try {
|
|
560
|
+
const response = await axios.post(endpoint, {}, {
|
|
561
|
+
headers,
|
|
562
|
+
timeout: 5000,
|
|
563
|
+
proxy: false
|
|
564
|
+
});
|
|
565
|
+
const payload = response.data;
|
|
566
|
+
if (payload.valid === true || Boolean(payload.payload)) {
|
|
567
|
+
return { valid: true, method: 'vendor_key', endpoint };
|
|
568
|
+
}
|
|
569
|
+
if (payload.valid === false) {
|
|
570
|
+
return {
|
|
571
|
+
valid: false,
|
|
572
|
+
method: 'vendor_key',
|
|
573
|
+
endpoint,
|
|
574
|
+
reason: this.extractAuthErrorMessage(payload) || 'API key is invalid'
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
catch (error) {
|
|
579
|
+
const normalizedError = this.normalizeServiceError(error);
|
|
580
|
+
const responsePayload = normalizedError.response?.data;
|
|
581
|
+
const responseCode = typeof responsePayload?.code === 'string' ? responsePayload.code : undefined;
|
|
582
|
+
const reason = this.extractAuthErrorMessage(responsePayload) || normalizedError.message || fallbackReason;
|
|
583
|
+
fallbackReason = reason;
|
|
584
|
+
// If auth gateway explicitly rejected API key, stop early.
|
|
585
|
+
if ((normalizedError.response?.status === 401 || normalizedError.response?.status === 403) &&
|
|
586
|
+
responseCode &&
|
|
587
|
+
responseCode !== 'AUTH_TOKEN_MISSING') {
|
|
588
|
+
return { valid: false, method: 'vendor_key', endpoint, reason };
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
// Fallback for deployments where reverse proxies don't forward custom auth headers on /verify.
|
|
593
|
+
for (const endpoint of this.getAuthVerificationEndpoints('/v1/auth/verify-api-key')) {
|
|
594
|
+
try {
|
|
595
|
+
const response = await axios.post(endpoint, {}, {
|
|
596
|
+
headers,
|
|
597
|
+
timeout: 5000,
|
|
598
|
+
proxy: false
|
|
599
|
+
});
|
|
600
|
+
const payload = response.data;
|
|
601
|
+
if (payload.valid === true) {
|
|
602
|
+
return { valid: true, method: 'vendor_key', endpoint };
|
|
603
|
+
}
|
|
604
|
+
if (payload.valid === false) {
|
|
605
|
+
return {
|
|
606
|
+
valid: false,
|
|
607
|
+
method: 'vendor_key',
|
|
608
|
+
endpoint,
|
|
609
|
+
reason: this.extractAuthErrorMessage(payload) || 'API key is invalid'
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
catch (error) {
|
|
614
|
+
const normalizedError = this.normalizeServiceError(error);
|
|
615
|
+
const responsePayload = normalizedError.response?.data;
|
|
616
|
+
fallbackReason = this.extractAuthErrorMessage(responsePayload) || normalizedError.message || fallbackReason;
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
return {
|
|
620
|
+
valid: false,
|
|
621
|
+
method: 'vendor_key',
|
|
622
|
+
reason: fallbackReason
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
async verifyCurrentCredentialsWithServer() {
|
|
626
|
+
await this.refreshTokenIfNeeded();
|
|
627
|
+
await this.discoverServices();
|
|
628
|
+
const token = this.getToken();
|
|
629
|
+
const vendorKey = await this.getVendorKeyAsync();
|
|
630
|
+
if (this.config.authMethod === 'vendor_key' && vendorKey) {
|
|
631
|
+
return this.verifyVendorKeyWithAuthGateway(vendorKey);
|
|
632
|
+
}
|
|
633
|
+
if (token) {
|
|
634
|
+
return this.verifyTokenWithAuthGateway(token);
|
|
635
|
+
}
|
|
636
|
+
if (vendorKey) {
|
|
637
|
+
return this.verifyVendorKeyWithAuthGateway(vendorKey);
|
|
638
|
+
}
|
|
639
|
+
return {
|
|
640
|
+
valid: false,
|
|
641
|
+
method: 'none',
|
|
642
|
+
reason: 'No credentials configured'
|
|
643
|
+
};
|
|
644
|
+
}
|
|
437
645
|
// Manual endpoint override functionality
|
|
438
646
|
async setManualEndpoints(endpoints) {
|
|
439
647
|
if (!this.config.discoveredServices) {
|
|
@@ -461,6 +669,17 @@ export class CLIConfig {
|
|
|
461
669
|
hasManualEndpointOverrides() {
|
|
462
670
|
return !!this.config.manualEndpointOverrides;
|
|
463
671
|
}
|
|
672
|
+
/**
|
|
673
|
+
* Clears the in-memory auth cache and removes the `lastValidated` timestamp.
|
|
674
|
+
* Called after a definitive 401 from the memory API so that the next
|
|
675
|
+
* `isAuthenticated()` call performs a fresh server verification rather than
|
|
676
|
+
* returning a stale cached result.
|
|
677
|
+
*/
|
|
678
|
+
async invalidateAuthCache() {
|
|
679
|
+
this.authCheckCache = null;
|
|
680
|
+
delete this.config.lastValidated;
|
|
681
|
+
await this.save().catch(() => { });
|
|
682
|
+
}
|
|
464
683
|
async clearManualEndpointOverrides() {
|
|
465
684
|
delete this.config.manualEndpointOverrides;
|
|
466
685
|
delete this.config.lastManualEndpointUpdate;
|
|
@@ -473,15 +692,20 @@ export class CLIConfig {
|
|
|
473
692
|
'https://auth.lanonasis.com';
|
|
474
693
|
}
|
|
475
694
|
// Enhanced authentication support
|
|
476
|
-
async setVendorKey(vendorKey) {
|
|
695
|
+
async setVendorKey(vendorKey, options = {}) {
|
|
477
696
|
const trimmedKey = typeof vendorKey === 'string' ? vendorKey.trim() : '';
|
|
478
697
|
// Minimal format validation (non-empty); rely on server-side checks for everything else
|
|
479
698
|
const formatValidation = this.validateVendorKeyFormat(trimmedKey);
|
|
480
699
|
if (formatValidation !== true) {
|
|
481
700
|
throw new Error(typeof formatValidation === 'string' ? formatValidation : 'Vendor key is invalid');
|
|
482
701
|
}
|
|
483
|
-
//
|
|
484
|
-
|
|
702
|
+
// Skip server-side validation when the caller already holds a valid auth credential
|
|
703
|
+
// (e.g. an OAuth access token being stored for MCP/API access — auth-gateway won't
|
|
704
|
+
// recognise it as a vendor key even though the memory API accepts it).
|
|
705
|
+
const isOAuthContext = ['oauth', 'oauth2'].includes(this.config.authMethod || '');
|
|
706
|
+
if (!options.skipServerValidation && !isOAuthContext) {
|
|
707
|
+
await this.validateVendorKeyWithServer(trimmedKey);
|
|
708
|
+
}
|
|
485
709
|
// Initialize and store using ApiKeyStorage from @lanonasis/oauth-client
|
|
486
710
|
// This handles encryption automatically (AES-256-GCM with machine-derived key)
|
|
487
711
|
await this.apiKeyStorage.initialize();
|
|
@@ -520,16 +744,12 @@ export class CLIConfig {
|
|
|
520
744
|
return;
|
|
521
745
|
}
|
|
522
746
|
try {
|
|
523
|
-
// Import axios dynamically to avoid circular dependency
|
|
524
|
-
// Ensure service discovery is done
|
|
525
747
|
await this.discoverServices();
|
|
526
|
-
const
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
'X-Project-Scope': 'lanonasis-maas'
|
|
532
|
-
}, { timeout: 10000, proxy: false });
|
|
748
|
+
const verification = await this.verifyVendorKeyWithAuthGateway(vendorKey);
|
|
749
|
+
if (verification.valid) {
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
throw new Error(verification.reason || 'Authentication failed. The key may be invalid, expired, or revoked.');
|
|
533
753
|
}
|
|
534
754
|
catch (error) {
|
|
535
755
|
const normalizedError = this.normalizeServiceError(error);
|
|
@@ -687,36 +907,40 @@ export class CLIConfig {
|
|
|
687
907
|
const vendorKey = await this.getVendorKeyAsync();
|
|
688
908
|
if (!vendorKey)
|
|
689
909
|
return false;
|
|
690
|
-
// Check cache first
|
|
910
|
+
// Check in-memory cache first (5-minute TTL)
|
|
691
911
|
if (this.authCheckCache && (Date.now() - this.authCheckCache.timestamp) < this.AUTH_CACHE_TTL) {
|
|
692
912
|
return this.authCheckCache.isValid;
|
|
693
913
|
}
|
|
694
|
-
//
|
|
914
|
+
// Track lastValidated for the offline grace period used in the catch block.
|
|
915
|
+
// The 24-hour skip-server-validation gate has been removed: it allowed expired/revoked
|
|
916
|
+
// keys to appear valid as long as they had been validated within the past day.
|
|
695
917
|
const lastValidated = this.config.lastValidated;
|
|
696
|
-
|
|
697
|
-
(Date.now() - new Date(lastValidated).getTime()) < (24 * 60 * 60 * 1000);
|
|
698
|
-
if (recentlyValidated) {
|
|
699
|
-
this.authCheckCache = { isValid: true, timestamp: Date.now() };
|
|
700
|
-
return true;
|
|
701
|
-
}
|
|
702
|
-
// Vendor key not recently validated - verify with server
|
|
918
|
+
// Verify with server on every cache-miss
|
|
703
919
|
try {
|
|
704
|
-
await this.
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
'X-Project-Scope': 'lanonasis-maas'
|
|
711
|
-
}, { timeout: 5000, proxy: false });
|
|
920
|
+
const verification = await this.verifyVendorKeyWithAuthGateway(vendorKey);
|
|
921
|
+
if (!verification.valid) {
|
|
922
|
+
// Auth gateway explicitly rejected the key — no grace period applies.
|
|
923
|
+
this.authCheckCache = { isValid: false, timestamp: Date.now() };
|
|
924
|
+
return false;
|
|
925
|
+
}
|
|
712
926
|
// Update last validated timestamp on success
|
|
713
927
|
this.config.lastValidated = new Date().toISOString();
|
|
714
928
|
await this.save().catch(() => { }); // Don't fail auth check if save fails
|
|
715
929
|
this.authCheckCache = { isValid: true, timestamp: Date.now() };
|
|
716
930
|
return true;
|
|
717
931
|
}
|
|
718
|
-
catch (
|
|
719
|
-
//
|
|
932
|
+
catch (err) {
|
|
933
|
+
// verifyVendorKeyWithAuthGateway throws only on network/timeout errors
|
|
934
|
+
// (explicit 401/403 returns {valid:false} without throwing).
|
|
935
|
+
// Apply the 7-day offline grace ONLY for genuine network failures.
|
|
936
|
+
const normalizedErr = this.normalizeServiceError(err);
|
|
937
|
+
const httpStatus = normalizedErr.response?.status ?? 0;
|
|
938
|
+
if (httpStatus === 401 || httpStatus === 403) {
|
|
939
|
+
// Explicit auth rejection propagated as an exception — definitely invalid.
|
|
940
|
+
this.authCheckCache = { isValid: false, timestamp: Date.now() };
|
|
941
|
+
return false;
|
|
942
|
+
}
|
|
943
|
+
// Network / server error — apply offline grace period
|
|
720
944
|
const gracePeriod = 7 * 24 * 60 * 60 * 1000;
|
|
721
945
|
const withinGracePeriod = lastValidated &&
|
|
722
946
|
(Date.now() - new Date(lastValidated).getTime()) < gracePeriod;
|
|
@@ -727,7 +951,6 @@ export class CLIConfig {
|
|
|
727
951
|
this.authCheckCache = { isValid: true, timestamp: Date.now() };
|
|
728
952
|
return true;
|
|
729
953
|
}
|
|
730
|
-
// Grace period expired - require server validation
|
|
731
954
|
if (process.env.CLI_VERBOSE === 'true') {
|
|
732
955
|
console.warn('⚠️ Vendor key validation failed and grace period expired');
|
|
733
956
|
}
|
|
@@ -947,22 +1170,14 @@ export class CLIConfig {
|
|
|
947
1170
|
if (!vendorKey && !token) {
|
|
948
1171
|
return false;
|
|
949
1172
|
}
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
if (vendorKey) {
|
|
958
|
-
headers['X-API-Key'] = vendorKey;
|
|
959
|
-
headers['X-Auth-Method'] = 'vendor_key';
|
|
960
|
-
}
|
|
961
|
-
else if (token) {
|
|
962
|
-
headers['Authorization'] = `Bearer ${token}`;
|
|
963
|
-
headers['X-Auth-Method'] = 'jwt';
|
|
1173
|
+
const verification = this.config.authMethod === 'vendor_key' && vendorKey
|
|
1174
|
+
? await this.verifyVendorKeyWithAuthGateway(vendorKey)
|
|
1175
|
+
: token
|
|
1176
|
+
? await this.verifyTokenWithAuthGateway(token)
|
|
1177
|
+
: await this.verifyVendorKeyWithAuthGateway(vendorKey);
|
|
1178
|
+
if (!verification.valid) {
|
|
1179
|
+
throw new Error(verification.reason || 'Stored credentials are invalid');
|
|
964
1180
|
}
|
|
965
|
-
await this.pingAuthHealth(axios, authBase, headers);
|
|
966
1181
|
// Update last validated timestamp
|
|
967
1182
|
this.config.lastValidated = new Date().toISOString();
|
|
968
1183
|
await this.resetFailureCount();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lanonasis/cli",
|
|
3
|
-
"version": "3.9.
|
|
3
|
+
"version": "3.9.7",
|
|
4
4
|
"description": "Professional CLI for LanOnasis Memory as a Service (MaaS) with MCP support, seamless inline editing, and enterprise-grade security",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"lanonasis",
|
|
@@ -52,37 +52,37 @@
|
|
|
52
52
|
"CHANGELOG.md"
|
|
53
53
|
],
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@lanonasis/oauth-client": "
|
|
55
|
+
"@lanonasis/oauth-client": "2.0.0",
|
|
56
56
|
"@lanonasis/security-sdk": "1.0.5",
|
|
57
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
58
|
-
"axios": "^1.
|
|
59
|
-
"chalk": "^5.
|
|
57
|
+
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
58
|
+
"axios": "^1.13.5",
|
|
59
|
+
"chalk": "^5.6.2",
|
|
60
60
|
"cli-progress": "^3.12.0",
|
|
61
|
-
"cli-table3": "^0.6.
|
|
62
|
-
"commander": "^
|
|
61
|
+
"cli-table3": "^0.6.5",
|
|
62
|
+
"commander": "^14.0.3",
|
|
63
63
|
"date-fns": "^4.1.0",
|
|
64
|
-
"dotenv": "^
|
|
65
|
-
"eventsource": "^4.
|
|
66
|
-
"inquirer": "^
|
|
64
|
+
"dotenv": "^17.3.1",
|
|
65
|
+
"eventsource": "^4.1.0",
|
|
66
|
+
"inquirer": "^13.2.5",
|
|
67
67
|
"jwt-decode": "^4.0.0",
|
|
68
|
-
"open": "^
|
|
69
|
-
"ora": "^
|
|
68
|
+
"open": "^11.0.0",
|
|
69
|
+
"ora": "^9.3.0",
|
|
70
70
|
"table": "^6.9.0",
|
|
71
71
|
"word-wrap": "^1.2.5",
|
|
72
|
-
"ws": "^8.
|
|
73
|
-
"zod": "^3.
|
|
72
|
+
"ws": "^8.19.0",
|
|
73
|
+
"zod": "^4.3.6"
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
|
76
|
-
"@jest/globals": "^
|
|
76
|
+
"@jest/globals": "^30.2.0",
|
|
77
77
|
"@types/cli-progress": "^3.11.6",
|
|
78
|
-
"@types/inquirer": "^9.0.
|
|
79
|
-
"@types/node": "^
|
|
80
|
-
"@types/ws": "^8.
|
|
81
|
-
"fast-check": "^
|
|
82
|
-
"jest": "^
|
|
83
|
-
"rimraf": "^
|
|
84
|
-
"ts-jest": "^29.
|
|
85
|
-
"typescript": "^5.
|
|
78
|
+
"@types/inquirer": "^9.0.9",
|
|
79
|
+
"@types/node": "^25.3.0",
|
|
80
|
+
"@types/ws": "^8.18.1",
|
|
81
|
+
"fast-check": "^4.5.3",
|
|
82
|
+
"jest": "^30.2.0",
|
|
83
|
+
"rimraf": "^6.1.3",
|
|
84
|
+
"ts-jest": "^29.4.6",
|
|
85
|
+
"typescript": "^5.9.3"
|
|
86
86
|
},
|
|
87
87
|
"scripts": {
|
|
88
88
|
"build": "rimraf dist && tsc -p tsconfig.json",
|