dexto 1.6.22 → 1.6.25
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/dist/cli/auth/api-client.d.ts +19 -1
- package/dist/cli/auth/api-client.d.ts.map +1 -1
- package/dist/cli/auth/api-client.js +92 -1
- package/dist/cli/auth/billing.d.ts +14 -0
- package/dist/cli/auth/billing.d.ts.map +1 -0
- package/dist/cli/auth/billing.js +35 -0
- package/dist/cli/auth/browser-launch.d.ts +1 -0
- package/dist/cli/auth/browser-launch.d.ts.map +1 -1
- package/dist/cli/auth/browser-launch.js +7 -0
- package/dist/cli/auth/constants.d.ts.map +1 -1
- package/dist/cli/auth/constants.js +1 -1
- package/dist/cli/auth/dexto-api-key.d.ts +2 -2
- package/dist/cli/auth/dexto-api-key.d.ts.map +1 -1
- package/dist/cli/auth/dexto-api-key.js +3 -7
- package/dist/cli/auth/index.d.ts +2 -1
- package/dist/cli/auth/index.d.ts.map +1 -1
- package/dist/cli/auth/index.js +2 -1
- package/dist/cli/auth/login-persistence.d.ts.map +1 -1
- package/dist/cli/auth/login-persistence.js +33 -3
- package/dist/cli/auth/service.d.ts +1 -0
- package/dist/cli/auth/service.d.ts.map +1 -1
- package/dist/cli/auth/service.js +16 -4
- package/dist/cli/cloud-chat.d.ts.map +1 -1
- package/dist/cli/cloud-chat.js +1 -0
- package/dist/cli/commands/auth/login.d.ts.map +1 -1
- package/dist/cli/commands/auth/login.js +7 -18
- package/dist/cli/commands/billing/status.d.ts.map +1 -1
- package/dist/cli/commands/billing/status.js +2 -3
- package/dist/cli/commands/setup.js +3 -8
- package/dist/cli/modes/cli.d.ts.map +1 -1
- package/dist/cli/modes/cli.js +3 -1
- package/dist/webui/assets/{index-DlW-GIHG.js → index-XTyP16n-.js} +88 -88
- package/dist/webui/assets/tanstack-CdDcRpJz.js +1 -0
- package/dist/webui/index.html +2 -2
- package/package.json +13 -13
- 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":"AAYA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAwBpD,MAAM,WAAW,uBAAuB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,uBAAuB,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,MAAM,sBAAsB,GAC5B;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,UAAU,CAAA;CAAE,GACtB;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,GACpB;IAAE,MAAM,EAAE,gBAAgB,CAAA;CAAE,GAC5B;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,uBAAuB,CAAA;CAAE,CAAC;AAE5D,MAAM,WAAW,oBAAoB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE;QACP,cAAc,EAAE,MAAM,CAAC;QACvB,cAAc,EAAE,MAAM,CAAC;QACvB,QAAQ,EAAE,MAAM,CACZ,MAAM,EACN;YACI,QAAQ,EAAE,MAAM,CAAC;YACjB,QAAQ,EAAE,MAAM,CAAC;YACjB,MAAM,EAAE,MAAM,CAAC;SAClB,CACJ,CAAC;KACL,CAAC;IACF,MAAM,EAAE,KAAK,CAAC;QACV,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;KACzB,CAAC,CAAC;CACN;AAED,UAAU,cAAc;IACpB,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CACpC;
|
|
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":"
|
|
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,
|
|
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
|
|
26
|
-
*
|
|
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,
|
|
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
|
|
101
|
-
*
|
|
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
|
-
|
|
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,
|
package/dist/cli/auth/index.d.ts
CHANGED
|
@@ -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"}
|
package/dist/cli/auth/index.js
CHANGED
|
@@ -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;
|
|
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;
|
|
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"}
|
package/dist/cli/auth/service.js
CHANGED
|
@@ -64,7 +64,7 @@ export async function isAuthenticated() {
|
|
|
64
64
|
const auth = await loadAuth();
|
|
65
65
|
return auth !== null;
|
|
66
66
|
}
|
|
67
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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"}
|
package/dist/cli/cloud-chat.js
CHANGED
|
@@ -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
|
}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/auth/login.ts"],"names":[],"mappings":"
|
|
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,
|
|
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
|
|
134
|
-
|
|
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
|
|
140
|
-
token,
|
|
141
|
-
|
|
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":"
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
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
|
-
|
|
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,
|
|
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"}
|
package/dist/cli/modes/cli.js
CHANGED
|
@@ -166,7 +166,7 @@ export async function runCliMode(context) {
|
|
|
166
166
|
console.info = noOp;
|
|
167
167
|
let inkError = undefined;
|
|
168
168
|
try {
|
|
169
|
-
const [{ startInkCliRefactored, setTuiRuntimeServices }, { registerGracefulShutdown }, { applyLayeredEnvironmentLoading }, { getProviderDisplayName, isValidApiKeyFormat, getProviderInstructions }, { performDeviceCodeLogin, persistOAuthLoginResult, ensureDextoApiKeyForAuthToken, loadAuth, storeAuth, removeAuth, removeDextoApiKeyFromEnv, }, { isUsingDextoCredits }, { canUseDextoProvider }, { capture },] = await Promise.all([
|
|
169
|
+
const [{ startInkCliRefactored, setTuiRuntimeServices }, { registerGracefulShutdown }, { applyLayeredEnvironmentLoading }, { getProviderDisplayName, isValidApiKeyFormat, getProviderInstructions }, { performDeviceCodeLogin, persistOAuthLoginResult, ensureDextoApiKeyForAuthToken, loadAuth, storeAuth, removeAuth, removeDextoApiKeyFromEnv, buildDextoBillingUrl, openDextoBillingPage, }, { isUsingDextoCredits }, { canUseDextoProvider }, { capture },] = await Promise.all([
|
|
170
170
|
import('@dexto/tui'),
|
|
171
171
|
import('../../utils/graceful-shutdown.js'),
|
|
172
172
|
import('../../utils/env.js'),
|
|
@@ -194,6 +194,8 @@ export async function runCliMode(context) {
|
|
|
194
194
|
removeDextoApiKeyFromEnv,
|
|
195
195
|
isUsingDextoCredits,
|
|
196
196
|
canUseDextoProvider,
|
|
197
|
+
buildDextoBillingUrl,
|
|
198
|
+
openDextoBillingPage,
|
|
197
199
|
});
|
|
198
200
|
await startInkCliRefactored(agent, cliSessionId, {
|
|
199
201
|
updateInfo: cliUpdateInfo ?? undefined,
|