@bonginkan/maria 4.2.10 → 4.2.13

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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # MARIA - AI Development Platform v4.2.10
1
+ # MARIA - AI Development Platform v4.2.13
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@bonginkan/maria.svg)](https://www.npmjs.com/package/@bonginkan/maria)
4
4
  [![License](https://img.shields.io/badge/license-Multi--tier-blue.svg)](LICENSE)
@@ -10,7 +10,7 @@
10
10
 
11
11
  > **Enterprise-grade AI development platform with 100% command availability and comprehensive fallback support**
12
12
 
13
- ## 🚀 What's New in v4.2.10 (September 3, 2025)
13
+ ## 🚀 What's New in v4.2.13 (September 3, 2025)
14
14
 
15
15
  ### 🏗️ Build Status - All Systems Operational ✅
16
16
  - **CLI NPM Package**: ESM + CJS builds successful (2.02MB/1.16MB)
@@ -61,6 +61,34 @@
61
61
  $ npm install -g @bonginkan/maria
62
62
  ```
63
63
 
64
+ ### 🪟 Windows: Add npm global prefix to PATH
65
+ On Windows, npm's global bin directory may not be on PATH by default. After installing, verify and add the directory returned by `npm prefix -g` to PATH.
66
+
67
+ ```powershell
68
+ # Show npm global prefix (this directory should be on PATH)
69
+ npm prefix -g;
70
+
71
+ # Temporarily add to current PowerShell session
72
+ $env:Path += ";" + (npm prefix -g).Trim(); Get-Command maria;
73
+
74
+ # Persist for the current user (idempotent)
75
+ $npmBin = (npm prefix -g).Trim();
76
+ $userPath = [Environment]::GetEnvironmentVariable('Path','User');
77
+ if ($userPath -notlike "*$npmBin*") {
78
+ [Environment]::SetEnvironmentVariable('Path', ($userPath.TrimEnd(';') + ";" + $npmBin), 'User');
79
+ "Added to PATH: $npmBin";
80
+ } else {
81
+ "Already on PATH: $npmBin";
82
+ }
83
+
84
+ # Restart PowerShell, then verify
85
+ maria --version;
86
+ ```
87
+
88
+ Notes:
89
+ - Default location is typically `%APPDATA%\npm` on Windows.
90
+ - You can also run the CLI without installing globally via: `npx @bonginkan/maria --help`
91
+
64
92
  ### 🔗 VS Code Extension (NEW)
65
93
  **AI-powered coding directly in your editor**
66
94
 
@@ -707,10 +735,10 @@ await secureWorkflow.executeWithAuth(workflowDefinition, securityContext);
707
735
  ### Quick Installation
708
736
  ```bash
709
737
  # Install globally (recommended)
710
- npm install -g @bonginkan/maria@4.2.10
738
+ npm install -g @bonginkan/maria@4.2.13
711
739
 
712
740
  # Verify installation
713
- maria --version # Should show v4.2.10
741
+ maria --version # Should show v4.2.13
714
742
 
715
743
  # Initialize with authentication
716
744
  maria /login # Setup OAuth2.0 + PKCE authentication
@@ -911,7 +939,7 @@ MARIA CODE is distributed under a comprehensive licensing system designed for in
911
939
 
912
940
  *MARIA v4.1.4 represents the pinnacle of multimodal AI development platform evolution - combining revolutionary voice-to-code capabilities, advanced memory systems, and comprehensive command ecosystems with enterprise-grade security and performance. This release establishes MARIA as the definitive choice for developers and Fortune 500 enterprises seeking intelligent, multimodal development experiences with GraphRAG intelligence, multilingual support, and zero-anxiety coding workflows.*
913
941
 
914
- **Transform your development experience today**: `npm install -g @bonginkan/maria@4.2.10`
942
+ **Transform your development experience today**: `npm install -g @bonginkan/maria@4.2.13`
915
943
 
916
944
  🌐 **Official Website**: [https://maria-code.ai](https://maria-code.ai)
917
945
  💬 **Community**: [https://discord.gg/SMSmSGcEQy](https://discord.gg/SMSmSGcEQy)
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "2.0.0",
3
- "generatedAt": "2025-09-04T04:59:03.918Z",
3
+ "generatedAt": "2025-09-04T07:10:40.845Z",
4
4
  "totalCommands": 76,
5
5
  "readyCount": 74,
6
6
  "partialCount": 1,
@@ -356,54 +356,54 @@
356
356
  "depsAvailable": true,
357
357
  "description": "About MARIA - version, features, and credits"
358
358
  },
359
- "configuration/setup": {
359
+ "conversation/clear": {
360
360
  "status": "READY",
361
361
  "hasExecute": true,
362
362
  "hasMetadata": true,
363
363
  "depsAvailable": true,
364
- "description": "First-time environment setup wizard"
364
+ "description": "Clear conversation history"
365
365
  },
366
- "conversation/clear": {
366
+ "configuration/setup": {
367
367
  "status": "READY",
368
368
  "hasExecute": true,
369
369
  "hasMetadata": true,
370
370
  "depsAvailable": true,
371
- "description": "Clear conversation history"
371
+ "description": "First-time environment setup wizard"
372
372
  },
373
- "business/sales-dashboard": {
373
+ "code/mm": {
374
374
  "status": "READY",
375
375
  "hasExecute": true,
376
376
  "hasMetadata": true,
377
377
  "depsAvailable": true,
378
- "description": "Sales metrics and dashboard"
378
+ "description": "Multimodal code generation (image/voice to code)"
379
379
  },
380
- "business/battlecard": {
380
+ "code/multimodal": {
381
381
  "status": "READY",
382
382
  "hasExecute": true,
383
383
  "hasMetadata": true,
384
384
  "depsAvailable": true,
385
- "description": "Competitive battlecard generator"
385
+ "description": "Advanced multimodal AI operations"
386
386
  },
387
- "code/mm": {
387
+ "code/code": {
388
388
  "status": "READY",
389
389
  "hasExecute": true,
390
390
  "hasMetadata": true,
391
391
  "depsAvailable": true,
392
- "description": "Multimodal code generation (image/voice to code)"
392
+ "description": "Generate code with AI assistance"
393
393
  },
394
- "code/multimodal": {
394
+ "business/sales-dashboard": {
395
395
  "status": "READY",
396
396
  "hasExecute": true,
397
397
  "hasMetadata": true,
398
398
  "depsAvailable": true,
399
- "description": "Advanced multimodal AI operations"
399
+ "description": "Sales metrics and dashboard"
400
400
  },
401
- "code/code": {
401
+ "business/battlecard": {
402
402
  "status": "READY",
403
403
  "hasExecute": true,
404
404
  "hasMetadata": true,
405
405
  "depsAvailable": true,
406
- "description": "Generate code with AI assistance"
406
+ "description": "Competitive battlecard generator"
407
407
  },
408
408
  "ai/gpu": {
409
409
  "status": "READY",
@@ -441,47 +441,47 @@
441
441
  "depsAvailable": true,
442
442
  "description": "AI-powered research and analysis"
443
443
  },
444
- "configuration/permissions": {
444
+ "core/update": {
445
445
  "status": "READY",
446
446
  "hasExecute": true,
447
447
  "hasMetadata": true,
448
448
  "depsAvailable": true,
449
- "description": "Manage permissions and access control"
449
+ "description": "Update project dependencies and configurations"
450
450
  },
451
- "configuration/model": {
451
+ "core/exit": {
452
452
  "status": "READY",
453
453
  "hasExecute": true,
454
454
  "hasMetadata": true,
455
455
  "depsAvailable": true,
456
- "description": "Select and configure AI model"
456
+ "description": "Exit MARIA CLI"
457
457
  },
458
- "configuration/unknown": {
458
+ "configuration/permissions": {
459
459
  "status": "READY",
460
460
  "hasExecute": true,
461
- "hasMetadata": false,
461
+ "hasMetadata": true,
462
462
  "depsAvailable": true,
463
- "description": "Handle unknown command fallback"
463
+ "description": "Manage permissions and access control"
464
464
  },
465
- "configuration/config": {
465
+ "configuration/model": {
466
466
  "status": "READY",
467
467
  "hasExecute": true,
468
468
  "hasMetadata": true,
469
469
  "depsAvailable": true,
470
- "description": "Configuration management"
470
+ "description": "Select and configure AI model"
471
471
  },
472
- "core/update": {
472
+ "configuration/unknown": {
473
473
  "status": "READY",
474
474
  "hasExecute": true,
475
- "hasMetadata": true,
475
+ "hasMetadata": false,
476
476
  "depsAvailable": true,
477
- "description": "Update project dependencies and configurations"
477
+ "description": "Handle unknown command fallback"
478
478
  },
479
- "core/exit": {
479
+ "configuration/config": {
480
480
  "status": "READY",
481
481
  "hasExecute": true,
482
482
  "hasMetadata": true,
483
483
  "depsAvailable": true,
484
- "description": "Exit MARIA CLI"
484
+ "description": "Configuration management"
485
485
  },
486
486
  "monitoring/monitor": {
487
487
  "status": "READY",
@@ -497,19 +497,19 @@
497
497
  "depsAvailable": true,
498
498
  "description": "Advanced memory service operations"
499
499
  },
500
- "core/enhanced-help": {
500
+ "configuration/hooks": {
501
501
  "status": "READY",
502
502
  "hasExecute": true,
503
503
  "hasMetadata": true,
504
504
  "depsAvailable": true,
505
- "description": "Advanced help system with interactive features"
505
+ "description": "Configure and manage command hooks"
506
506
  },
507
- "configuration/hooks": {
507
+ "core/enhanced-help": {
508
508
  "status": "READY",
509
509
  "hasExecute": true,
510
510
  "hasMetadata": true,
511
511
  "depsAvailable": true,
512
- "description": "Configure and manage command hooks"
512
+ "description": "Advanced help system with interactive features"
513
513
  },
514
514
  "business/analytics": {
515
515
  "status": "READY",
@@ -21942,8 +21942,8 @@ var init_package = __esm({
21942
21942
  "package.json"() {
21943
21943
  package_default = {
21944
21944
  name: "@bonginkan/maria",
21945
- version: "4.2.10",
21946
- description: "\u{1F680} MARIA v4.2.10 - Enterprise AI Development Platform with 100% Command Availability. Features 74 production-ready commands with comprehensive fallback implementation, local LLM support, and zero external dependencies. Includes natural language coding, AI safety evaluation, intelligent evolution system, episodic memory with PII masking, and real-time monitoring dashboard. Built with TypeScript AST-powered code generation, OAuth2.0 + PKCE authentication, quantum-resistant cryptography, and enterprise-grade performance.",
21945
+ version: "4.2.13",
21946
+ description: "\u{1F680} MARIA v4.2.13 - Enterprise AI Development Platform with 100% Command Availability. Features 74 production-ready commands with comprehensive fallback implementation, local LLM support, and zero external dependencies. Includes natural language coding, AI safety evaluation, intelligent evolution system, episodic memory with PII masking, and real-time monitoring dashboard. Built with TypeScript AST-powered code generation, OAuth2.0 + PKCE authentication, quantum-resistant cryptography, and enterprise-grade performance.",
21947
21947
  keywords: [
21948
21948
  "ai",
21949
21949
  "cli",
@@ -23150,6 +23150,7 @@ var init_AuthenticationManager = __esm({
23150
23150
  this.clientId = config2.clientId;
23151
23151
  this.initialized = true;
23152
23152
  } catch (error2) {
23153
+ console.warn("Auth config initialization failed, using fallbacks:", error2);
23153
23154
  this.authBase = this.getAuthBaseUrl();
23154
23155
  this.apiBase = this.getApiBaseUrl();
23155
23156
  this.clientId = process.env.MARIA_CLIENT_ID || "maria-cli";
@@ -23196,7 +23197,8 @@ var init_AuthenticationManager = __esm({
23196
23197
  return await this.refreshToken();
23197
23198
  }
23198
23199
  return true;
23199
- } catch {
23200
+ } catch (error2) {
23201
+ console.error("isAuthenticated failed:", error2);
23200
23202
  return false;
23201
23203
  }
23202
23204
  }
@@ -23260,6 +23262,7 @@ var init_AuthenticationManager = __esm({
23260
23262
  if (error2 instanceof AuthenticationRequiredError || error2 instanceof QuotaExceededError) {
23261
23263
  throw error2;
23262
23264
  }
23265
+ console.error("getCurrentUser failed:", error2);
23263
23266
  throw new Error(ERROR_MESSAGES.NETWORK_ERROR);
23264
23267
  }
23265
23268
  }
@@ -23277,12 +23280,17 @@ var init_AuthenticationManager = __esm({
23277
23280
  return await this.loginWithLocalMock();
23278
23281
  }
23279
23282
  let tokens;
23280
- if (options.device) {
23283
+ const forceDevice = options.device || process.env.MARIA_AUTH_DEVICE_FLOW === "true" || !this.canLaunchBrowser();
23284
+ if (forceDevice) {
23285
+ if (!options.device) {
23286
+ console.warn("PKCE is unavailable in this environment; using device flow.");
23287
+ }
23281
23288
  tokens = await this.loginWithDeviceFlow();
23282
23289
  } else {
23283
23290
  try {
23284
23291
  tokens = await this.loginWithPKCEFlow();
23285
23292
  } catch (error2) {
23293
+ console.error("PKCE flow error:", error2);
23286
23294
  if (error2.message?.includes("ECONNREFUSED") || error2.message?.includes("fetch failed")) {
23287
23295
  console.error("\n\u274C Authentication service is currently unavailable");
23288
23296
  console.error("Please try one of the following:");
@@ -23304,6 +23312,7 @@ var init_AuthenticationManager = __esm({
23304
23312
  const user = await this.getCurrentUser();
23305
23313
  return { success: true, user, tokens };
23306
23314
  } catch (error2) {
23315
+ console.error("Login failed:", error2);
23307
23316
  return {
23308
23317
  success: false,
23309
23318
  error: error2.message || "Login failed"
@@ -23395,7 +23404,8 @@ var init_AuthenticationManager = __esm({
23395
23404
  };
23396
23405
  await this.tokenStorage.save(updatedTokens);
23397
23406
  return true;
23398
- } catch {
23407
+ } catch (error2) {
23408
+ console.error("Token refresh failed:", error2);
23399
23409
  return false;
23400
23410
  }
23401
23411
  }
@@ -23437,6 +23447,7 @@ var init_AuthenticationManager = __esm({
23437
23447
  await (0, import_open.default)(authUrl);
23438
23448
  } catch (error2) {
23439
23449
  server.close();
23450
+ console.error("Failed to open browser for authentication:", error2);
23440
23451
  throw new Error("Failed to open browser");
23441
23452
  }
23442
23453
  const authCode = await this.waitForCallback(server, pkceParams.state);
@@ -23460,57 +23471,62 @@ var init_AuthenticationManager = __esm({
23460
23471
  * Login with device flow (fallback)
23461
23472
  */
23462
23473
  async loginWithDeviceFlow() {
23463
- const response2 = await fetch(`${this.authBase}/oauth/device/start`, {
23464
- method: "POST",
23465
- headers: { "Content-Type": "application/json" },
23466
- body: JSON.stringify({
23467
- client_id: this.clientId,
23468
- scope: "user:profile user:inference org:create_api_key"
23469
- })
23470
- });
23471
- if (!response2.ok) {
23472
- throw new Error(`Device flow start failed: ${response2.statusText}`);
23473
- }
23474
- const raw = await response2.json();
23475
- const deviceResponse = {
23476
- verificationUri: raw.verification_uri || raw.verificationUri || "https://auth.maria-code.ai/device",
23477
- userCode: raw.user_code || raw.userCode || "",
23478
- deviceCode: raw.device_code || raw.deviceCode || "",
23479
- interval: (typeof raw.interval === "number" ? raw.interval : parseInt(String(raw.interval || 5), 10)) || 5,
23480
- expiresIn: (typeof raw.expires_in === "number" ? raw.expires_in : parseInt(String(raw.expires_in || raw.expiresIn || 600), 10)) || 600
23481
- };
23482
- const verificationUrl = deviceResponse.verificationUri || `${this.authBase}/device`;
23483
- console.log(`\u{1F510} Device Login`);
23484
- console.log(`Open: ${verificationUrl}`);
23485
- console.log(`Code: ${deviceResponse.userCode}`);
23486
- const deadline = Date.now() + deviceResponse.expiresIn * 1e3;
23487
- const intervalMs = Math.max(1500, deviceResponse.interval * 1e3);
23488
- while (Date.now() < deadline) {
23489
- await this.sleep(intervalMs);
23490
- const finishResponse = await fetch(`${this.authBase}/oauth/device/finish`, {
23474
+ try {
23475
+ const response2 = await fetch(`${this.authBase}/oauth/device/start`, {
23491
23476
  method: "POST",
23492
23477
  headers: { "Content-Type": "application/json" },
23493
23478
  body: JSON.stringify({
23494
23479
  client_id: this.clientId,
23495
- device_code: deviceResponse.deviceCode
23480
+ scope: "user:profile user:inference org:create_api_key"
23496
23481
  })
23497
23482
  });
23498
- if (finishResponse.status === 428 || finishResponse.status === 400) {
23499
- continue;
23500
- }
23501
- if (!finishResponse.ok) {
23502
- throw new Error(`Device flow failed: ${finishResponse.statusText}`);
23503
- }
23504
- const tokens = await finishResponse.json();
23505
- return {
23506
- idToken: tokens.id_token || tokens.access_token || "",
23507
- accessToken: tokens.access_token || tokens.id_token || "",
23508
- refreshToken: tokens.refresh_token || "",
23509
- customToken: tokens.custom_token,
23510
- expiresAt: Date.now() + (tokens.expires_in ? Number(tokens.expires_in) : 600) * 1e3
23483
+ if (!response2.ok) {
23484
+ throw new Error(`Device flow start failed: ${response2.statusText}`);
23485
+ }
23486
+ const raw = await response2.json();
23487
+ const deviceResponse = {
23488
+ verificationUri: raw.verification_uri || raw.verificationUri || "https://auth.maria-code.ai/device",
23489
+ userCode: raw.user_code || raw.userCode || "",
23490
+ deviceCode: raw.device_code || raw.deviceCode || "",
23491
+ interval: (typeof raw.interval === "number" ? raw.interval : parseInt(String(raw.interval || 5), 10)) || 5,
23492
+ expiresIn: (typeof raw.expires_in === "number" ? raw.expires_in : parseInt(String(raw.expires_in || raw.expiresIn || 600), 10)) || 600
23511
23493
  };
23494
+ const verificationUrl = deviceResponse.verificationUri || `${this.authBase}/device`;
23495
+ console.log(`\u{1F510} Device Login`);
23496
+ console.log(`Open: ${verificationUrl}`);
23497
+ console.log(`Code: ${deviceResponse.userCode}`);
23498
+ const deadline = Date.now() + deviceResponse.expiresIn * 1e3;
23499
+ const intervalMs = Math.max(1500, deviceResponse.interval * 1e3);
23500
+ while (Date.now() < deadline) {
23501
+ await this.sleep(intervalMs);
23502
+ const finishResponse = await fetch(`${this.authBase}/oauth/device/finish`, {
23503
+ method: "POST",
23504
+ headers: { "Content-Type": "application/json" },
23505
+ body: JSON.stringify({
23506
+ client_id: this.clientId,
23507
+ device_code: deviceResponse.deviceCode
23508
+ })
23509
+ });
23510
+ if (finishResponse.status === 428 || finishResponse.status === 400) {
23511
+ continue;
23512
+ }
23513
+ if (!finishResponse.ok) {
23514
+ throw new Error(`Device flow failed: ${finishResponse.statusText}`);
23515
+ }
23516
+ const tokens = await finishResponse.json();
23517
+ return {
23518
+ idToken: tokens.id_token || tokens.access_token || "",
23519
+ accessToken: tokens.access_token || tokens.id_token || "",
23520
+ refreshToken: tokens.refresh_token || "",
23521
+ customToken: tokens.custom_token,
23522
+ expiresAt: Date.now() + (tokens.expires_in ? Number(tokens.expires_in) : 600) * 1e3
23523
+ };
23524
+ }
23525
+ throw new Error(ERROR_MESSAGES.LOGIN_TIMEOUT);
23526
+ } catch (error2) {
23527
+ console.error("Device flow error:", error2);
23528
+ throw error2;
23512
23529
  }
23513
- throw new Error(ERROR_MESSAGES.LOGIN_TIMEOUT);
23514
23530
  }
23515
23531
  /**
23516
23532
  * Generate PKCE parameters
@@ -23549,8 +23565,10 @@ var init_AuthenticationManager = __esm({
23549
23565
  } catch (error2) {
23550
23566
  lastError = error2;
23551
23567
  if (error2.code !== "EADDRINUSE") {
23568
+ console.error("Failed to start callback server:", error2);
23552
23569
  throw error2;
23553
23570
  }
23571
+ console.warn("Callback server port in use, retrying...", error2?.message || error2);
23554
23572
  }
23555
23573
  }
23556
23574
  throw lastError || new Error("Failed to find available port");
@@ -23582,6 +23600,7 @@ var init_AuthenticationManager = __esm({
23582
23600
  return new Promise((resolve4, reject) => {
23583
23601
  const timeout = setTimeout(() => {
23584
23602
  server.close();
23603
+ console.error("OAuth callback timed out");
23585
23604
  reject(new Error(ERROR_MESSAGES.LOGIN_TIMEOUT));
23586
23605
  }, 5 * 60 * 1e3);
23587
23606
  server.on("request", (req, res) => {
@@ -23594,6 +23613,7 @@ var init_AuthenticationManager = __esm({
23594
23613
  res.writeHead(400, { "Content-Type": "text/html" });
23595
23614
  res.end(this.getErrorPage(error2));
23596
23615
  clearTimeout(timeout);
23616
+ console.error("OAuth callback returned error:", error2);
23597
23617
  reject(new Error(error2));
23598
23618
  return;
23599
23619
  }
@@ -23601,6 +23621,7 @@ var init_AuthenticationManager = __esm({
23601
23621
  res.writeHead(400, { "Content-Type": "text/html" });
23602
23622
  res.end(this.getErrorPage("Invalid state parameter"));
23603
23623
  clearTimeout(timeout);
23624
+ console.error("OAuth callback invalid state", { received: state, expected: expectedState });
23604
23625
  reject(new Error(ERROR_MESSAGES.INVALID_STATE));
23605
23626
  return;
23606
23627
  }
@@ -23618,28 +23639,39 @@ var init_AuthenticationManager = __esm({
23618
23639
  * Exchange authorization code for tokens
23619
23640
  */
23620
23641
  async exchangeCodeForTokens(code, codeVerifier, redirectUri) {
23621
- const response2 = await fetch(`${this.authBase}/oauth/token`, {
23622
- method: "POST",
23623
- headers: { "Content-Type": "application/json" },
23624
- body: JSON.stringify({
23625
- grant_type: "authorization_code",
23626
- client_id: this.clientId,
23627
- code,
23628
- code_verifier: codeVerifier,
23629
- redirect_uri: redirectUri
23630
- })
23631
- });
23632
- if (!response2.ok) {
23633
- throw new Error(`Token exchange failed: ${response2.statusText}`);
23642
+ try {
23643
+ const response2 = await fetch(`${this.authBase}/oauth/token`, {
23644
+ method: "POST",
23645
+ headers: { "Content-Type": "application/json" },
23646
+ body: JSON.stringify({
23647
+ grant_type: "authorization_code",
23648
+ client_id: this.clientId,
23649
+ code,
23650
+ code_verifier: codeVerifier,
23651
+ redirect_uri: redirectUri
23652
+ })
23653
+ });
23654
+ if (!response2.ok) {
23655
+ let bodyText = "";
23656
+ try {
23657
+ bodyText = await response2.text();
23658
+ } catch {
23659
+ }
23660
+ console.error("Token exchange failed:", response2.status, response2.statusText, bodyText);
23661
+ throw new Error(`Token exchange failed: ${response2.status} ${response2.statusText}`);
23662
+ }
23663
+ const tokens = await response2.json();
23664
+ return {
23665
+ idToken: tokens.id_token,
23666
+ accessToken: tokens.access_token,
23667
+ refreshToken: tokens.refresh_token,
23668
+ customToken: tokens.custom_token,
23669
+ expiresAt: Date.now() + tokens.expires_in * 1e3
23670
+ };
23671
+ } catch (error2) {
23672
+ console.error("Token exchange request error:", error2);
23673
+ throw error2;
23634
23674
  }
23635
- const tokens = await response2.json();
23636
- return {
23637
- idToken: tokens.id_token,
23638
- accessToken: tokens.access_token,
23639
- refreshToken: tokens.refresh_token,
23640
- customToken: tokens.custom_token,
23641
- expiresAt: Date.now() + tokens.expires_in * 1e3
23642
- };
23643
23675
  }
23644
23676
  /**
23645
23677
  * Revoke tokens on server