dexto 1.6.24 → 1.6.26

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.
Files changed (37) hide show
  1. package/dist/cli/auth/api-client.d.ts +19 -1
  2. package/dist/cli/auth/api-client.d.ts.map +1 -1
  3. package/dist/cli/auth/api-client.js +92 -1
  4. package/dist/cli/auth/billing.d.ts +14 -0
  5. package/dist/cli/auth/billing.d.ts.map +1 -0
  6. package/dist/cli/auth/billing.js +35 -0
  7. package/dist/cli/auth/browser-launch.d.ts +1 -0
  8. package/dist/cli/auth/browser-launch.d.ts.map +1 -1
  9. package/dist/cli/auth/browser-launch.js +7 -0
  10. package/dist/cli/auth/constants.d.ts.map +1 -1
  11. package/dist/cli/auth/constants.js +1 -1
  12. package/dist/cli/auth/dexto-api-key.d.ts +2 -2
  13. package/dist/cli/auth/dexto-api-key.d.ts.map +1 -1
  14. package/dist/cli/auth/dexto-api-key.js +3 -7
  15. package/dist/cli/auth/index.d.ts +2 -1
  16. package/dist/cli/auth/index.d.ts.map +1 -1
  17. package/dist/cli/auth/index.js +2 -1
  18. package/dist/cli/auth/login-persistence.d.ts.map +1 -1
  19. package/dist/cli/auth/login-persistence.js +33 -3
  20. package/dist/cli/auth/service.d.ts +1 -0
  21. package/dist/cli/auth/service.d.ts.map +1 -1
  22. package/dist/cli/auth/service.js +16 -4
  23. package/dist/cli/cloud-chat.d.ts.map +1 -1
  24. package/dist/cli/cloud-chat.js +4 -3
  25. package/dist/cli/commands/auth/login.d.ts.map +1 -1
  26. package/dist/cli/commands/auth/login.js +7 -18
  27. package/dist/cli/commands/billing/status.d.ts.map +1 -1
  28. package/dist/cli/commands/billing/status.js +2 -3
  29. package/dist/cli/commands/setup.js +3 -8
  30. package/dist/cli/modes/cli.d.ts.map +1 -1
  31. package/dist/cli/modes/cli.js +3 -1
  32. package/dist/index-main.js +2 -0
  33. package/dist/webui/assets/{index-MAdBaUdd.js → index-XTyP16n-.js} +75 -75
  34. package/dist/webui/assets/tanstack-CdDcRpJz.js +1 -0
  35. package/dist/webui/index.html +2 -2
  36. package/package.json +13 -13
  37. package/dist/webui/assets/tanstack-BL5ags_d.js +0 -1
@@ -46,6 +46,13 @@ export interface UsageSummaryResponse {
46
46
  output_tokens: number;
47
47
  }>;
48
48
  }
49
+ export interface BillingBalanceResponse {
50
+ creditsUsd: number;
51
+ }
52
+ export interface BillingCheckoutSessionResponse {
53
+ checkoutUrl: string;
54
+ checkoutSessionId: string;
55
+ }
49
56
  interface RequestOptions {
50
57
  signal?: AbortSignal | undefined;
51
58
  }
@@ -75,12 +82,23 @@ export declare class DextoApiClient {
75
82
  provisionDextoApiKey(authToken: string, name?: string, regenerate?: boolean): Promise<{
76
83
  dextoApiKey: string;
77
84
  keyId: string;
78
- isNewKey: boolean;
79
85
  }>;
80
86
  /**
81
87
  * Get usage summary (balance + MTD usage + recent history)
82
88
  */
83
89
  getUsageSummary(apiKey: string): Promise<UsageSummaryResponse>;
90
+ /**
91
+ * Get the current Dexto billing balance for the authenticated user.
92
+ */
93
+ getBillingBalance(authToken: string, options: RequestOptions): Promise<BillingBalanceResponse>;
94
+ /**
95
+ * Create a hosted top-up checkout session for the authenticated user.
96
+ */
97
+ createBillingCheckoutSession(authToken: string, options: {
98
+ creditsUsd: number;
99
+ returnUrl?: string | undefined;
100
+ signal?: AbortSignal | undefined;
101
+ }): Promise<BillingCheckoutSessionResponse>;
84
102
  /**
85
103
  * Start device code login at the platform.
86
104
  */
@@ -1 +1 @@
1
- {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../../src/cli/auth/api-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../../src/cli/auth/api-client.ts"],"names":[],"mappings":"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"}
@@ -185,6 +185,33 @@ function parseUsageSummaryResponse(payload) {
185
185
  recent,
186
186
  };
187
187
  }
188
+ function parseBillingBalanceResponse(payload) {
189
+ if (typeof payload !== 'object' || payload === null) {
190
+ throw new Error('Invalid response from API');
191
+ }
192
+ const creditsUsd = parseNumber(Reflect.get(payload, 'credits_usd')) ??
193
+ parseNumber(Reflect.get(payload, 'creditsUsd'));
194
+ if (creditsUsd === null) {
195
+ throw new Error('Invalid response from API');
196
+ }
197
+ return { creditsUsd };
198
+ }
199
+ function parseBillingCheckoutSessionResponse(payload) {
200
+ if (typeof payload !== 'object' || payload === null) {
201
+ throw new Error('Invalid response from API');
202
+ }
203
+ const checkoutUrl = parseString(Reflect.get(payload, 'checkout_url')) ??
204
+ parseString(Reflect.get(payload, 'checkoutUrl'));
205
+ const checkoutSessionId = parseString(Reflect.get(payload, 'checkout_session_id')) ??
206
+ parseString(Reflect.get(payload, 'checkoutSessionId'));
207
+ if (!checkoutUrl || !checkoutSessionId) {
208
+ throw new Error('Invalid response from API');
209
+ }
210
+ return {
211
+ checkoutUrl,
212
+ checkoutSessionId,
213
+ };
214
+ }
188
215
  function parseValidateResponse(payload) {
189
216
  if (typeof payload !== 'object' || payload === null) {
190
217
  return false;
@@ -376,7 +403,6 @@ export class DextoApiClient {
376
403
  return {
377
404
  dextoApiKey: createdKey.dextoApiKey,
378
405
  keyId: createdKey.keyId,
379
- isNewKey: true,
380
406
  };
381
407
  }
382
408
  catch (error) {
@@ -409,6 +435,71 @@ export class DextoApiClient {
409
435
  throw error;
410
436
  }
411
437
  }
438
+ /**
439
+ * Get the current Dexto billing balance for the authenticated user.
440
+ */
441
+ async getBillingBalance(authToken, options) {
442
+ try {
443
+ logger.debug('Fetching billing balance');
444
+ const response = await fetch(this.getPlatformUrl('/api/billing/balance'), {
445
+ method: 'GET',
446
+ headers: {
447
+ Authorization: `Bearer ${authToken}`,
448
+ },
449
+ signal: this.createRequestSignal(options.signal),
450
+ });
451
+ if (!response.ok) {
452
+ const rawText = await response.text();
453
+ throw new Error(`API request failed: ${formatHttpFailure(response.status, null, rawText)}`);
454
+ }
455
+ const payload = await response.json();
456
+ return parseBillingBalanceResponse(payload);
457
+ }
458
+ catch (error) {
459
+ logger.error('Error fetching billing balance', {
460
+ error: error instanceof Error ? error.message : String(error),
461
+ });
462
+ throw error;
463
+ }
464
+ }
465
+ /**
466
+ * Create a hosted top-up checkout session for the authenticated user.
467
+ */
468
+ async createBillingCheckoutSession(authToken, options) {
469
+ try {
470
+ if (!Number.isFinite(options.creditsUsd) || options.creditsUsd <= 0) {
471
+ throw new Error('creditsUsd must be a positive number');
472
+ }
473
+ logger.debug('Creating billing checkout session', {
474
+ creditsUsd: options.creditsUsd,
475
+ });
476
+ const response = await fetch(this.getPlatformUrl('/api/billing/checkout-session'), {
477
+ method: 'POST',
478
+ headers: {
479
+ Authorization: `Bearer ${authToken}`,
480
+ 'Content-Type': 'application/json',
481
+ },
482
+ body: JSON.stringify({
483
+ credits_usd: options.creditsUsd,
484
+ ...(options.returnUrl ? { return_url: options.returnUrl } : {}),
485
+ }),
486
+ signal: this.createRequestSignal(options.signal),
487
+ });
488
+ if (!response.ok) {
489
+ const rawText = await response.text();
490
+ throw new Error(`API request failed: ${formatHttpFailure(response.status, null, rawText)}`);
491
+ }
492
+ const payload = await response.json();
493
+ return parseBillingCheckoutSessionResponse(payload);
494
+ }
495
+ catch (error) {
496
+ logger.error('Error creating billing checkout session', {
497
+ error: error instanceof Error ? error.message : String(error),
498
+ creditsUsd: options.creditsUsd,
499
+ });
500
+ throw error;
501
+ }
502
+ }
412
503
  /**
413
504
  * Start device code login at the platform.
414
505
  */
@@ -0,0 +1,14 @@
1
+ import type { BillingCheckoutSessionResponse } from './api-client.js';
2
+ export declare function buildDextoBillingUrl(options: {
3
+ creditsUsd?: number | undefined;
4
+ baseUrl?: string | undefined;
5
+ }): string;
6
+ export declare function getBillingBalanceForCurrentLogin(): Promise<number | null>;
7
+ export declare function createBillingCheckoutForCurrentLogin(options: {
8
+ creditsUsd: number;
9
+ returnUrl?: string | undefined;
10
+ }): Promise<BillingCheckoutSessionResponse>;
11
+ export declare function openDextoBillingPage(options: {
12
+ url?: string | undefined;
13
+ }): Promise<void>;
14
+ //# sourceMappingURL=billing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"billing.d.ts","sourceRoot":"","sources":["../../../src/cli/auth/billing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,iBAAiB,CAAC;AAUtE,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC1C,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC,GAAG,MAAM,CAQT;AAED,wBAAsB,gCAAgC,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQ/E;AAED,wBAAsB,oCAAoC,CAAC,OAAO,EAAE;IAChE,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC,GAAG,OAAO,CAAC,8BAA8B,CAAC,CAU1C;AAED,wBAAsB,oBAAoB,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/F"}
@@ -0,0 +1,35 @@
1
+ import { getDextoApiClient } from './api-client.js';
2
+ import { openBrowserUrl } from './browser-launch.js';
3
+ import { DEXTO_CREDITS_URL } from './constants.js';
4
+ import { getAuthTokenQuietly } from './service.js';
5
+ function notLoggedInError() {
6
+ return new Error('Not logged in to Dexto');
7
+ }
8
+ export function buildDextoBillingUrl(options) {
9
+ const url = new URL(options.baseUrl ?? DEXTO_CREDITS_URL);
10
+ if (typeof options.creditsUsd === 'number' && Number.isFinite(options.creditsUsd)) {
11
+ url.searchParams.set('credits_usd', String(options.creditsUsd));
12
+ }
13
+ return url.toString();
14
+ }
15
+ export async function getBillingBalanceForCurrentLogin() {
16
+ const authToken = await getAuthTokenQuietly();
17
+ if (!authToken) {
18
+ return null;
19
+ }
20
+ const response = await getDextoApiClient().getBillingBalance(authToken, {});
21
+ return response.creditsUsd;
22
+ }
23
+ export async function createBillingCheckoutForCurrentLogin(options) {
24
+ const authToken = await getAuthTokenQuietly();
25
+ if (!authToken) {
26
+ throw notLoggedInError();
27
+ }
28
+ return getDextoApiClient().createBillingCheckoutSession(authToken, {
29
+ ...options,
30
+ returnUrl: options.returnUrl ?? DEXTO_CREDITS_URL,
31
+ });
32
+ }
33
+ export async function openDextoBillingPage(options) {
34
+ await openBrowserUrl(options.url ?? DEXTO_CREDITS_URL);
35
+ }
@@ -3,4 +3,5 @@ export interface BrowserLaunchContext {
3
3
  platform: NodeJS.Platform;
4
4
  }
5
5
  export declare function shouldAttemptBrowserLaunch(context?: BrowserLaunchContext): boolean;
6
+ export declare function openBrowserUrl(url: string, context?: BrowserLaunchContext): Promise<void>;
6
7
  //# sourceMappingURL=browser-launch.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"browser-launch.d.ts","sourceRoot":"","sources":["../../../src/cli/auth/browser-launch.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,oBAAoB;IACjC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;CAC7B;AAKD,wBAAgB,0BAA0B,CACtC,OAAO,GAAE,oBAAuE,GACjF,OAAO,CAwBT"}
1
+ {"version":3,"file":"browser-launch.d.ts","sourceRoot":"","sources":["../../../src/cli/auth/browser-launch.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,oBAAoB;IACjC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;CAC7B;AAKD,wBAAgB,0BAA0B,CACtC,OAAO,GAAE,oBAAuE,GACjF,OAAO,CAwBT;AAED,wBAAsB,cAAc,CAChC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,oBAAuE,GACjF,OAAO,CAAC,IAAI,CAAC,CAMf"}
@@ -1,5 +1,6 @@
1
1
  // packages/cli/src/cli/auth/browser-launch.ts
2
2
  // Environment checks for deciding whether automatic browser launch is likely to work.
3
+ import open from 'open';
3
4
  const BROWSER_BLOCKLIST = new Set(['www-browser', 'none', 'false', '0']);
4
5
  const DISPLAY_ENV_VARS = ['DISPLAY', 'WAYLAND_DISPLAY', 'MIR_SOCKET'];
5
6
  export function shouldAttemptBrowserLaunch(context = { env: process.env, platform: process.platform }) {
@@ -22,3 +23,9 @@ export function shouldAttemptBrowserLaunch(context = { env: process.env, platfor
22
23
  }
23
24
  return true;
24
25
  }
26
+ export async function openBrowserUrl(url, context = { env: process.env, platform: process.platform }) {
27
+ if (!shouldAttemptBrowserLaunch(context)) {
28
+ throw new Error('Automatic browser launch is unavailable in this environment');
29
+ }
30
+ await open(url, { wait: false });
31
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/cli/auth/constants.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,YAAY,QAAyE,CAAC;AACnG,eAAO,MAAM,iBAAiB,QAEwL,CAAC;AAEvN;;GAEG;AACH,eAAO,MAAM,aAAa,QAAsD,CAAC;AAEjF;;GAEG;AACH,eAAO,MAAM,kBAAkB,QAAgE,CAAC;AAEhG;;GAEG;AACH,eAAO,MAAM,iBAAiB,QAC+C,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/cli/auth/constants.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,YAAY,QAAyE,CAAC;AACnG,eAAO,MAAM,iBAAiB,QAEwL,CAAC;AAEvN;;GAEG;AACH,eAAO,MAAM,aAAa,QAAsD,CAAC;AAEjF;;GAEG;AACH,eAAO,MAAM,kBAAkB,QAAgE,CAAC;AAEhG;;GAEG;AACH,eAAO,MAAM,iBAAiB,QACwD,CAAC"}
@@ -30,4 +30,4 @@ export const DEXTO_PLATFORM_URL = process.env.DEXTO_PLATFORM_URL || 'https://pla
30
30
  /**
31
31
  * Dexto Nova credits purchase URL
32
32
  */
33
- export const DEXTO_CREDITS_URL = process.env.DEXTO_CREDITS_URL || 'https://app.dexto.ai/dashboard/billing';
33
+ export const DEXTO_CREDITS_URL = process.env.DEXTO_CREDITS_URL || 'https://app.dexto.ai/dashboard/settings/billing';
@@ -22,8 +22,8 @@ export declare function removeDextoApiKeyFromEnv(options?: {
22
22
  *
23
23
  * - If a local key exists and validates, it is re-saved to .env (sync) and returned.
24
24
  * - If a local key exists but is invalid, it is rotated (regenerated) and returned.
25
- * - If no local key exists, a key is provisioned. If one exists server-side but can't
26
- * be returned, it is regenerated to obtain the value.
25
+ * - If no local key exists, a managed key is provisioned. If a same-name managed key
26
+ * already exists server-side, provisioning rotates it to obtain a fresh secret value.
27
27
  *
28
28
  * Returns `null` if provisioning fails (OAuth login can still succeed without it).
29
29
  */
@@ -1 +1 @@
1
- {"version":3,"file":"dexto-api-key.d.ts","sourceRoot":"","sources":["../../../src/cli/auth/dexto-api-key.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,+BAA+B,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAEvF,MAAM,WAAW,0BAA0B;IACvC,KAAK,EAAE,+BAA+B,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,wBAAwB;IACrC,QAAQ,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,0BAA0B,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CACzE;AAaD;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA4BxE;AAED,wBAAsB,wBAAwB,CAAC,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC;IAC9F,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACzB,CAAC,CAsDD;AAED;;;;;;;;;GASG;AACH,wBAAsB,6BAA6B,CAC/C,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,wBAA6B,GACvC,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,CAAC,CAkE/D"}
1
+ {"version":3,"file":"dexto-api-key.d.ts","sourceRoot":"","sources":["../../../src/cli/auth/dexto-api-key.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,+BAA+B,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAEvF,MAAM,WAAW,0BAA0B;IACvC,KAAK,EAAE,+BAA+B,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,wBAAwB;IACrC,QAAQ,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,0BAA0B,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CACzE;AAaD;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA4BxE;AAED,wBAAsB,wBAAwB,CAAC,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC;IAC9F,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACzB,CAAC,CAsDD;AAED;;;;;;;;;GASG;AACH,wBAAsB,6BAA6B,CAC/C,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,wBAA6B,GACvC,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,CAAC,CA6D/D"}
@@ -97,8 +97,8 @@ export async function removeDextoApiKeyFromEnv(options = {}) {
97
97
  *
98
98
  * - If a local key exists and validates, it is re-saved to .env (sync) and returned.
99
99
  * - If a local key exists but is invalid, it is rotated (regenerated) and returned.
100
- * - If no local key exists, a key is provisioned. If one exists server-side but can't
101
- * be returned, it is regenerated to obtain the value.
100
+ * - If no local key exists, a managed key is provisioned. If a same-name managed key
101
+ * already exists server-side, provisioning rotates it to obtain a fresh secret value.
102
102
  *
103
103
  * Returns `null` if provisioning fails (OAuth login can still succeed without it).
104
104
  */
@@ -137,11 +137,7 @@ export async function ensureDextoApiKeyForAuthToken(authToken, options = {}) {
137
137
  return { dextoApiKey: rotated.dextoApiKey, keyId: rotated.keyId };
138
138
  }
139
139
  status('info', 'Provisioning Dexto API key...');
140
- let provisioned = await apiClient.provisionDextoApiKey(authToken);
141
- if (!provisioned.isNewKey) {
142
- status('warning', 'Key exists on server, regenerating...');
143
- provisioned = await apiClient.provisionDextoApiKey(authToken, 'Dexto CLI Key', true);
144
- }
140
+ const provisioned = await apiClient.provisionDextoApiKey(authToken);
145
141
  await storeAuth({
146
142
  ...auth,
147
143
  dextoApiKey: provisioned.dextoApiKey,
@@ -1,8 +1,9 @@
1
- export { type AuthConfig, storeAuth, loadAuth, removeAuth, isAuthenticated, getAuthToken, getDextoApiKey, getAuthFilePath, } from './service.js';
1
+ export { type AuthConfig, storeAuth, loadAuth, removeAuth, isAuthenticated, getAuthToken, getAuthTokenQuietly, getDextoApiKey, getAuthFilePath, } from './service.js';
2
2
  export { type OAuthResult } from './oauth.js';
3
3
  export { type DeviceLoginPrompt, performDeviceCodeLogin } from './device.js';
4
4
  export { type PersistOAuthLoginOptions, type PersistedLoginResult, persistOAuthLoginResult, } from './login-persistence.js';
5
5
  export { type UsageSummaryResponse, DextoApiClient, getDextoApiClient } from './api-client.js';
6
6
  export { SUPABASE_URL, SUPABASE_ANON_KEY, DEXTO_API_URL, DEXTO_PLATFORM_URL } from './constants.js';
7
+ export { buildDextoBillingUrl, getBillingBalanceForCurrentLogin, createBillingCheckoutForCurrentLogin, openDextoBillingPage, } from './billing.js';
7
8
  export { type DextoApiKeyProvisionStatus, type DextoApiKeyProvisionStatusLevel, type EnsureDextoApiKeyOptions, ensureDextoApiKeyForAuthToken, saveDextoApiKeyToEnv, removeDextoApiKeyFromEnv, } from './dexto-api-key.js';
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/auth/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACH,KAAK,UAAU,EACf,SAAS,EACT,QAAQ,EACR,UAAU,EACV,eAAe,EACf,YAAY,EACZ,cAAc,EACd,eAAe,GAClB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,EAAE,KAAK,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAE7E,OAAO,EACH,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,uBAAuB,GAC1B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,KAAK,oBAAoB,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAE/F,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEpG,OAAO,EACH,KAAK,0BAA0B,EAC/B,KAAK,+BAA+B,EACpC,KAAK,wBAAwB,EAC7B,6BAA6B,EAC7B,oBAAoB,EACpB,wBAAwB,GAC3B,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/auth/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACH,KAAK,UAAU,EACf,SAAS,EACT,QAAQ,EACR,UAAU,EACV,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,cAAc,EACd,eAAe,GAClB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,EAAE,KAAK,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAE7E,OAAO,EACH,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,uBAAuB,GAC1B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,KAAK,oBAAoB,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAE/F,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEpG,OAAO,EACH,oBAAoB,EACpB,gCAAgC,EAChC,oCAAoC,EACpC,oBAAoB,GACvB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACH,KAAK,0BAA0B,EAC/B,KAAK,+BAA+B,EACpC,KAAK,wBAAwB,EAC7B,6BAA6B,EAC7B,oBAAoB,EACpB,wBAAwB,GAC3B,MAAM,oBAAoB,CAAC"}
@@ -1,8 +1,9 @@
1
1
  // packages/cli/src/cli/auth/index.ts
2
2
  // Public exports for auth module
3
- export { storeAuth, loadAuth, removeAuth, isAuthenticated, getAuthToken, getDextoApiKey, getAuthFilePath, } from './service.js';
3
+ export { storeAuth, loadAuth, removeAuth, isAuthenticated, getAuthToken, getAuthTokenQuietly, getDextoApiKey, getAuthFilePath, } from './service.js';
4
4
  export { performDeviceCodeLogin } from './device.js';
5
5
  export { persistOAuthLoginResult, } from './login-persistence.js';
6
6
  export { DextoApiClient, getDextoApiClient } from './api-client.js';
7
7
  export { SUPABASE_URL, SUPABASE_ANON_KEY, DEXTO_API_URL, DEXTO_PLATFORM_URL } from './constants.js';
8
+ export { buildDextoBillingUrl, getBillingBalanceForCurrentLogin, createBillingCheckoutForCurrentLogin, openDextoBillingPage, } from './billing.js';
8
9
  export { ensureDextoApiKeyForAuthToken, saveDextoApiKeyToEnv, removeDextoApiKeyFromEnv, } from './dexto-api-key.js';
@@ -1 +1 @@
1
- {"version":3,"file":"login-persistence.d.ts","sourceRoot":"","sources":["../../../src/cli/auth/login-persistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,0BAA0B,EAAiC,MAAM,oBAAoB,CAAC;AACpG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,MAAM,WAAW,wBAAwB;IACrC,iBAAiB,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,0BAA0B,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CAClF;AAED,MAAM,WAAW,oBAAoB;IACjC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,cAAc,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAsB,uBAAuB,CACzC,MAAM,EAAE,WAAW,EACnB,OAAO,GAAE,wBAA6B,GACvC,OAAO,CAAC,oBAAoB,CAAC,CAsB/B"}
1
+ {"version":3,"file":"login-persistence.d.ts","sourceRoot":"","sources":["../../../src/cli/auth/login-persistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,0BAA0B,EAAiC,MAAM,oBAAoB,CAAC;AACpG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,MAAM,WAAW,wBAAwB;IACrC,iBAAiB,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,0BAA0B,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CAClF;AAED,MAAM,WAAW,oBAAoB;IACjC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,cAAc,EAAE,OAAO,CAAC;CAC3B;AA4CD,wBAAsB,uBAAuB,CACzC,MAAM,EAAE,WAAW,EACnB,OAAO,GAAE,wBAA6B,GACvC,OAAO,CAAC,oBAAoB,CAAC,CAyB/B"}
@@ -1,7 +1,36 @@
1
1
  import { ensureDextoApiKeyForAuthToken } from './dexto-api-key.js';
2
- import { storeAuth } from './service.js';
2
+ import { loadAuth, storeAuth } from './service.js';
3
+ function isSameAuthenticatedUser(existingAuth, user) {
4
+ if (!existingAuth || !user) {
5
+ return false;
6
+ }
7
+ if (existingAuth.userId && user.id) {
8
+ return existingAuth.userId === user.id;
9
+ }
10
+ if (existingAuth.email && user.email) {
11
+ return existingAuth.email.toLowerCase() === user.email.toLowerCase();
12
+ }
13
+ return false;
14
+ }
15
+ function getPreservedDextoApiKey(existingAuth, user) {
16
+ if (!existingAuth?.dextoApiKey || !isSameAuthenticatedUser(existingAuth, user)) {
17
+ return null;
18
+ }
19
+ const isProvisionedKey = existingAuth.dextoApiKeySource === 'provisioned' ||
20
+ (existingAuth.dextoApiKeySource === undefined && Boolean(existingAuth.dextoKeyId));
21
+ if (!isProvisionedKey) {
22
+ return null;
23
+ }
24
+ return {
25
+ dextoApiKey: existingAuth.dextoApiKey,
26
+ ...(existingAuth.dextoKeyId ? { dextoKeyId: existingAuth.dextoKeyId } : {}),
27
+ dextoApiKeySource: 'provisioned',
28
+ };
29
+ }
3
30
  export async function persistOAuthLoginResult(result, options = {}) {
31
+ const existingAuth = await loadAuth();
4
32
  const expiresAt = result.expiresIn ? Date.now() + result.expiresIn * 1000 : undefined;
33
+ const preservedDextoApiKey = getPreservedDextoApiKey(existingAuth, result.user);
5
34
  await storeAuth({
6
35
  token: result.accessToken,
7
36
  refreshToken: result.refreshToken,
@@ -9,6 +38,7 @@ export async function persistOAuthLoginResult(result, options = {}) {
9
38
  email: result.user?.email,
10
39
  createdAt: Date.now(),
11
40
  expiresAt,
41
+ ...(preservedDextoApiKey ?? {}),
12
42
  });
13
43
  const ensured = await ensureDextoApiKeyForAuthToken(result.accessToken, {
14
44
  onStatus: options.onProvisionStatus,
@@ -16,7 +46,7 @@ export async function persistOAuthLoginResult(result, options = {}) {
16
46
  return {
17
47
  email: result.user?.email,
18
48
  userId: result.user?.id,
19
- keyId: ensured?.keyId ?? undefined,
20
- hasDextoApiKey: Boolean(ensured?.dextoApiKey),
49
+ keyId: ensured?.keyId ?? preservedDextoApiKey?.dextoKeyId ?? undefined,
50
+ hasDextoApiKey: Boolean(ensured?.dextoApiKey ?? preservedDextoApiKey?.dextoApiKey),
21
51
  };
22
52
  }
@@ -16,6 +16,7 @@ export declare function loadAuth(): Promise<AuthConfig | null>;
16
16
  export declare function removeAuth(): Promise<void>;
17
17
  export declare function isAuthenticated(): Promise<boolean>;
18
18
  export declare function getAuthToken(): Promise<string | null>;
19
+ export declare function getAuthTokenQuietly(): Promise<string | null>;
19
20
  export declare function getDextoApiKey(): Promise<string | null>;
20
21
  export declare function getAuthFilePath(): string;
21
22
  //# sourceMappingURL=service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/cli/auth/service.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,UAAU;IACvB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,iBAAiB,CAAC,EAAE,aAAa,GAAG,eAAe,GAAG,SAAS,CAAC;CACnE;AAkBD,wBAAsB,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAQjE;AAED,wBAAsB,QAAQ,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CA4B3D;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAOhD;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAGxD;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA4C3D;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQ7D;AA8CD,wBAAgB,eAAe,IAAI,MAAM,CAExC"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/cli/auth/service.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,UAAU;IACvB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,iBAAiB,CAAC,EAAE,aAAa,GAAG,eAAe,GAAG,SAAS,CAAC;CACnE;AAkBD,wBAAsB,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAQjE;AAED,wBAAsB,QAAQ,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CA4B3D;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAOhD;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAGxD;AAsDD,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAE3D;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAElE;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQ7D;AA8CD,wBAAgB,eAAe,IAAI,MAAM,CAExC"}
@@ -64,7 +64,7 @@ export async function isAuthenticated() {
64
64
  const auth = await loadAuth();
65
65
  return auth !== null;
66
66
  }
67
- export async function getAuthToken() {
67
+ async function resolveAuthToken(options) {
68
68
  const auth = await loadAuth();
69
69
  if (!auth) {
70
70
  return null;
@@ -81,11 +81,15 @@ export async function getAuthToken() {
81
81
  return null;
82
82
  }
83
83
  logger.debug('Access token expired or expiring soon, refreshing...');
84
- console.log(chalk.cyan('🔄 Access token expiring soon, refreshing...'));
84
+ if (!options.quiet) {
85
+ console.log(chalk.cyan('🔄 Access token expiring soon, refreshing...'));
86
+ }
85
87
  const refreshResult = await refreshAccessToken(auth.refreshToken);
86
88
  if (!refreshResult) {
87
89
  logger.debug('Token refresh failed, removing auth');
88
- console.log(chalk.red('❌ Token refresh failed. Please login again.'));
90
+ if (!options.quiet) {
91
+ console.log(chalk.red('❌ Token refresh failed. Please login again.'));
92
+ }
89
93
  await removeAuth();
90
94
  return null;
91
95
  }
@@ -97,9 +101,17 @@ export async function getAuthToken() {
97
101
  expiresAt: newExpiresAt,
98
102
  });
99
103
  logger.debug('Token refreshed successfully');
100
- console.log(chalk.green('✅ Access token refreshed successfully'));
104
+ if (!options.quiet) {
105
+ console.log(chalk.green('✅ Access token refreshed successfully'));
106
+ }
101
107
  return refreshResult.accessToken;
102
108
  }
109
+ export async function getAuthToken() {
110
+ return resolveAuthToken({ quiet: false });
111
+ }
112
+ export async function getAuthTokenQuietly() {
113
+ return resolveAuthToken({ quiet: true });
114
+ }
103
115
  export async function getDextoApiKey() {
104
116
  // Explicit env var takes priority (for CI, testing, account override)
105
117
  if (process.env.DEXTO_API_KEY?.trim()) {
@@ -1 +1 @@
1
- {"version":3,"file":"cloud-chat.d.ts","sourceRoot":"","sources":["../../src/cli/cloud-chat.ts"],"names":[],"mappings":"AAAA,OAAO,EAIH,KAAK,aAAa,EASrB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAyB,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAGjE,MAAM,WAAW,wBAAwB;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAK1D,KAAK,qBAAqB,GAAG,UAAU,CAAC,YAAY,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AASrF,KAAK,gBAAgB,GAAG,eAAe,CAAC;AAkNxC,wBAAgB,0BAA0B,CACtC,QAAQ,EAAE,aAAa,CAAC,mBAAmB,CAAC,GAC7C,qBAAqB,GAAG,IAAI,CA8B9B;AA4CD,wBAAgB,uBAAuB,CACnC,MAAM,EAAE,YAAY,EACpB,YAAY,EAAE,MAAM,GACrB,gBAAgB,CAqhBlB;AAED,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBxF"}
1
+ {"version":3,"file":"cloud-chat.d.ts","sourceRoot":"","sources":["../../src/cli/cloud-chat.ts"],"names":[],"mappings":"AAAA,OAAO,EAIH,KAAK,aAAa,EASrB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAyB,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAGjE,MAAM,WAAW,wBAAwB;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAK1D,KAAK,qBAAqB,GAAG,UAAU,CAAC,YAAY,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AASrF,KAAK,gBAAgB,GAAG,eAAe,CAAC;AAkNxC,wBAAgB,0BAA0B,CACtC,QAAQ,EAAE,aAAa,CAAC,mBAAmB,CAAC,GAC7C,qBAAqB,GAAG,IAAI,CA8B9B;AA4CD,wBAAgB,uBAAuB,CACnC,MAAM,EAAE,YAAY,EACpB,YAAY,EAAE,MAAM,GACrB,gBAAgB,CAuhBlB;AAED,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBxF"}
@@ -504,6 +504,7 @@ export function createCloudAgentBackend(client, cloudAgentId) {
504
504
  throw unsupportedCloudFeature('Session forking');
505
505
  }),
506
506
  getCurrentLLMConfig: ((sessionId) => currentLLMConfig(sessionId)),
507
+ hasSessionLLMOverride: (() => false),
507
508
  switchLLM: (async () => {
508
509
  throw unsupportedCloudFeature('Model switching');
509
510
  }),
@@ -629,13 +630,13 @@ export function createCloudAgentBackend(client, cloudAgentId) {
629
630
  setGlobalDisabledTools: ((toolNames) => {
630
631
  globalDisabledTools.splice(0, globalDisabledTools.length, ...toolNames);
631
632
  }),
632
- setSessionDisabledTools: ((sessionId, toolNames) => {
633
+ setSessionDisabledTools: (async (sessionId, toolNames) => {
633
634
  sessionDisabledTools.set(sessionId, [...toolNames]);
634
635
  }),
635
- setSessionAutoApproveTools: ((sessionId, toolNames) => {
636
+ setSessionAutoApproveTools: (async (sessionId, toolNames) => {
636
637
  sessionAutoApproveTools.set(sessionId, [...toolNames]);
637
638
  }),
638
- getSessionAutoApproveTools: ((sessionId) => {
639
+ getSessionAutoApproveTools: (async (sessionId) => {
639
640
  return sessionAutoApproveTools.get(sessionId) ?? [];
640
641
  }),
641
642
  getMcpServersWithStatus: (() => []),
@@ -1 +1 @@
1
- {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/auth/login.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,mBAAmB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB;AAgBD,wBAAsB,kBAAkB,CAAC,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiEzF;AAGD,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAErD;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CA6BvD"}
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/auth/login.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,mBAAmB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB;AAgBD,wBAAsB,kBAAkB,CAAC,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiEzF;AAGD,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAErD;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CA6BvD"}
@@ -1,8 +1,7 @@
1
1
  // packages/cli/src/cli/commands/auth/login.ts
2
2
  import chalk from 'chalk';
3
3
  import * as p from '@clack/prompts';
4
- import { getDextoApiClient, isAuthenticated, loadAuth, performDeviceCodeLogin, persistOAuthLoginResult, storeAuth, ensureDextoApiKeyForAuthToken, } from '../../auth/index.js';
5
- import { logger } from '@dexto/core';
4
+ import { getDextoApiClient, isAuthenticated, loadAuth, performDeviceCodeLogin, persistOAuthLoginResult, storeAuth, } from '../../auth/index.js';
6
5
  function isCancellationError(errorMessage) {
7
6
  const lower = errorMessage.toLowerCase();
8
7
  return (lower.includes('canceled') ||
@@ -130,17 +129,17 @@ async function handleTokenLogin(tokenInput) {
130
129
  const spinner = p.spinner();
131
130
  spinner.start('Verifying token...');
132
131
  try {
133
- const isValid = await verifyToken(token);
134
- if (!isValid) {
132
+ const apiClient = getDextoApiClient();
133
+ const user = await apiClient.fetchSupabaseUser(token);
134
+ if (!user) {
135
135
  spinner.stop('Invalid token');
136
136
  throw new Error('Token verification failed');
137
137
  }
138
138
  spinner.stop('Token verified!');
139
- await storeAuth({
140
- token,
141
- createdAt: Date.now(),
139
+ await persistOAuthLoginResult({
140
+ accessToken: token,
141
+ user,
142
142
  });
143
- await ensureDextoApiKeyForAuthToken(token);
144
143
  return true;
145
144
  }
146
145
  catch (error) {
@@ -148,13 +147,3 @@ async function handleTokenLogin(tokenInput) {
148
147
  throw error;
149
148
  }
150
149
  }
151
- async function verifyToken(token) {
152
- try {
153
- const apiClient = getDextoApiClient();
154
- return apiClient.validateSupabaseAccessToken(token);
155
- }
156
- catch (error) {
157
- logger.debug(`Token verification failed: ${error instanceof Error ? error.message : String(error)}`);
158
- return false;
159
- }
160
- }
@@ -1 +1 @@
1
- {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/billing/status.ts"],"names":[],"mappings":"AAOA;;;GAGG;AACH,wBAAsB,0BAA0B,CAAC,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CA4E/F"}
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/billing/status.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,wBAAsB,0BAA0B,CAAC,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CA4E/F"}
@@ -1,7 +1,6 @@
1
1
  // packages/cli/src/cli/commands/billing/status.ts
2
2
  import chalk from 'chalk';
3
- import open from 'open';
4
- import { loadAuth, getDextoApiClient } from '../../auth/index.js';
3
+ import { loadAuth, getDextoApiClient, openDextoBillingPage } from '../../auth/index.js';
5
4
  import { DEXTO_CREDITS_URL } from '../../auth/constants.js';
6
5
  /**
7
6
  * Handle the `dexto billing` command.
@@ -72,7 +71,7 @@ export async function handleBillingStatusCommand(options = {}) {
72
71
  }
73
72
  async function openCreditsPage() {
74
73
  try {
75
- await open(DEXTO_CREDITS_URL);
74
+ await openDextoBillingPage({});
76
75
  }
77
76
  catch (error) {
78
77
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -13,7 +13,7 @@ import { executeCommand } from '../utils/self-management.js';
13
13
  import { requiresSetup } from '../utils/setup-utils.js';
14
14
  import { canUseDextoProvider } from '../utils/dexto-setup.js';
15
15
  import { handleAutoLogin } from './auth/login.js';
16
- import { loadAuth, getDextoApiClient } from '../auth/index.js';
16
+ import { loadAuth, getBillingBalanceForCurrentLogin, openDextoBillingPage } from '../auth/index.js';
17
17
  import { DEXTO_CREDITS_URL } from '../auth/constants.js';
18
18
  import * as p from '@clack/prompts';
19
19
  import { capture } from '../../analytics/index.js';
@@ -918,7 +918,7 @@ async function handleDextoProviderSetup(options = {}) {
918
918
  }
919
919
  async function openCreditsPage() {
920
920
  try {
921
- await open(DEXTO_CREDITS_URL);
921
+ await openDextoBillingPage({});
922
922
  }
923
923
  catch (error) {
924
924
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -928,12 +928,7 @@ async function openCreditsPage() {
928
928
  }
929
929
  async function getCreditsBalance() {
930
930
  try {
931
- const auth = await loadAuth();
932
- if (!auth?.dextoApiKey)
933
- return null;
934
- const apiClient = getDextoApiClient();
935
- const usage = await apiClient.getUsageSummary(auth.dextoApiKey);
936
- return usage.credits_usd;
931
+ return await getBillingBalanceForCurrentLogin();
937
932
  }
938
933
  catch {
939
934
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/cli/modes/cli.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAuBpD,wBAAsB,UAAU,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAuQxE"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/cli/modes/cli.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAuBpD,wBAAsB,UAAU,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA2QxE"}