dexto 1.7.1 → 1.8.0

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 (40) hide show
  1. package/README.md +4 -7
  2. package/dist/agents/coding-agent/coding-agent.yml +0 -5
  3. package/dist/agents/default-agent.yml +0 -6
  4. package/dist/cli/auth/api-client.d.ts +9 -7
  5. package/dist/cli/auth/api-client.d.ts.map +1 -1
  6. package/dist/cli/auth/api-client.js +42 -64
  7. package/dist/cli/auth/device.d.ts +2 -2
  8. package/dist/cli/auth/device.d.ts.map +1 -1
  9. package/dist/cli/auth/device.js +3 -12
  10. package/dist/cli/auth/index.d.ts +2 -1
  11. package/dist/cli/auth/index.d.ts.map +1 -1
  12. package/dist/cli/auth/index.js +1 -1
  13. package/dist/cli/auth/login-persistence.d.ts +2 -0
  14. package/dist/cli/auth/login-persistence.d.ts.map +1 -1
  15. package/dist/cli/auth/login-persistence.js +12 -0
  16. package/dist/cli/auth/types.d.ts +4 -5
  17. package/dist/cli/auth/types.d.ts.map +1 -1
  18. package/dist/cli/cloud-chat.d.ts.map +1 -1
  19. package/dist/cli/cloud-chat.js +65 -24
  20. package/dist/cli/commands/auth/login.d.ts +4 -1
  21. package/dist/cli/commands/auth/login.d.ts.map +1 -1
  22. package/dist/cli/commands/auth/login.js +7 -8
  23. package/dist/cli/commands/auth/register.d.ts.map +1 -1
  24. package/dist/cli/commands/auth/register.js +2 -0
  25. package/dist/cli/commands/create-image.d.ts.map +1 -1
  26. package/dist/cli/commands/create-image.js +1 -13
  27. package/dist/cli/commands/init.d.ts.map +1 -1
  28. package/dist/cli/commands/init.js +19 -27
  29. package/dist/cli/commands/run/headless.d.ts.map +1 -1
  30. package/dist/cli/commands/run/headless.js +75 -65
  31. package/dist/cli/modes/cli.js +2 -2
  32. package/dist/cli/utils/scaffolding-utils.d.ts.map +1 -1
  33. package/dist/cli/utils/scaffolding-utils.js +1 -9
  34. package/dist/cli/utils/template-engine.d.ts +0 -12
  35. package/dist/cli/utils/template-engine.d.ts.map +1 -1
  36. package/dist/cli/utils/template-engine.js +5 -116
  37. package/dist/index-main.js +9 -5
  38. package/dist/webui/assets/{index-UG5Fuw_8.js → index-M9d4U7k5.js} +114 -114
  39. package/dist/webui/index.html +1 -1
  40. package/package.json +12 -12
package/README.md CHANGED
@@ -116,7 +116,7 @@ Upgrade/uninstall and migration troubleshooting live in docs:
116
116
  ### Run
117
117
 
118
118
  ```bash
119
- # Start Dexto
119
+ # Start Dexto (launches setup wizard on first run)
120
120
  dexto
121
121
  ```
122
122
 
@@ -132,8 +132,6 @@ dexto --help # Explore all options
132
132
 
133
133
  **Inside the interactive CLI**, type `/` to explore commands—switch models, manage sessions, configure tools, and more.
134
134
 
135
- If Dexto has not been set up yet, the first interactive launch opens the generic `dexto setup` flow before starting. Existing provider keys in your environment are detected there, so you can keep startup simple without inheriting the wrong bundled provider by accident.
136
-
137
135
  ### Manage Settings
138
136
 
139
137
  ```bash
@@ -194,8 +192,6 @@ permissions:
194
192
  alwaysAllow:
195
193
  - mcp--filesystem--read_file
196
194
  - mcp--filesystem--list_directory
197
- alwaysDeny:
198
- - mcp--filesystem--delete_file
199
195
  ```
200
196
 
201
197
  Agents remember which tools you've approved per session.
@@ -597,8 +593,9 @@ Test tools before deploying:
597
593
  Usage: dexto [options] [command] [prompt...]
598
594
 
599
595
  Basic Usage:
600
- dexto or dexto --mode cli Start interactive CLI (default)
601
- dexto "query" Run one-shot query
596
+ dexto Start web UI (default)
597
+ dexto "query" Run one-shot query
598
+ dexto --mode cli Interactive CLI
602
599
 
603
600
  Session Management:
604
601
  dexto -c Continue last conversation
@@ -130,11 +130,6 @@ permissions:
130
130
  - wait_for # Wait for background tasks without approval
131
131
  - check_task # Check background tasks without approval
132
132
 
133
- # Tools that are always denied (dangerous operations)
134
- # Uncomment to restrict certain operations
135
- # alwaysDeny:
136
- # - bash_exec # Require approval for all shell commands
137
-
138
133
  # Compaction configuration - automatically summarizes conversation when context is full
139
134
  compaction:
140
135
  type: reactive-overflow
@@ -97,12 +97,6 @@ permissions:
97
97
  - mcp--list_directory
98
98
  - mcp--list_allowed_directories
99
99
 
100
- # Tools that are always denied (high-risk, destructive operations)
101
- # Deny list takes precedence over allow list
102
- # alwaysDeny:
103
- # - mcp--filesystem--delete_file
104
- # - mcp--playwright--execute_script
105
-
106
100
  # Elicitation configuration - separate from tool confirmation
107
101
  # Allows auto-approve for tools while still supporting user input requests
108
102
  elicitation:
@@ -7,11 +7,13 @@ export interface DeviceCodeStartResponse {
7
7
  expiresIn: number;
8
8
  interval: number;
9
9
  }
10
- export interface DeviceCodeTokenResponse {
11
- accessToken: string;
12
- refreshToken?: string | null;
13
- expiresIn?: number | null;
14
- expiresAt?: number | null;
10
+ export interface DeviceCodeApiKeyResponse {
11
+ id: string;
12
+ keyDisplay: string;
13
+ name: string;
14
+ scopes: string[];
15
+ status: string;
16
+ fullKey: string;
15
17
  }
16
18
  export type DeviceCodePollResponse = {
17
19
  status: 'pending';
@@ -24,8 +26,8 @@ export type DeviceCodePollResponse = {
24
26
  } | {
25
27
  status: 'transientError';
26
28
  } | {
27
- status: 'success';
28
- token: DeviceCodeTokenResponse;
29
+ status: 'approved';
30
+ apiKey: DeviceCodeApiKeyResponse;
29
31
  };
30
32
  export interface UsageSummaryResponse {
31
33
  credits_usd: number;
@@ -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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"}
@@ -30,16 +30,11 @@ function parseDeviceCodeStartResponse(payload) {
30
30
  if (typeof payload !== 'object' || payload === null) {
31
31
  throw new Error('Invalid device start response');
32
32
  }
33
- const deviceCode = parseString(Reflect.get(payload, 'device_code')) ??
34
- parseString(Reflect.get(payload, 'deviceCode'));
35
- const userCode = parseString(Reflect.get(payload, 'user_code')) ??
36
- parseString(Reflect.get(payload, 'userCode'));
37
- const verificationUrl = parseString(Reflect.get(payload, 'verification_uri')) ??
38
- parseString(Reflect.get(payload, 'verificationUrl'));
39
- const verificationUrlComplete = parseString(Reflect.get(payload, 'verification_uri_complete')) ??
40
- parseString(Reflect.get(payload, 'verificationUrlComplete'));
41
- const expiresIn = parseNumber(Reflect.get(payload, 'expires_in')) ??
42
- parseNumber(Reflect.get(payload, 'expiresIn'));
33
+ const deviceCode = parseString(Reflect.get(payload, 'deviceCode'));
34
+ const userCode = parseString(Reflect.get(payload, 'userCode'));
35
+ const verificationUrl = parseString(Reflect.get(payload, 'verificationUri'));
36
+ const verificationUrlComplete = parseString(Reflect.get(payload, 'verificationUriComplete'));
37
+ const expiresIn = parseNumber(Reflect.get(payload, 'expiresIn'));
43
38
  const interval = parseNumber(Reflect.get(payload, 'interval'));
44
39
  if (!deviceCode || !userCode || !verificationUrl || !expiresIn || !interval) {
45
40
  throw new Error('Device start response missing required fields');
@@ -53,26 +48,41 @@ function parseDeviceCodeStartResponse(payload) {
53
48
  interval,
54
49
  };
55
50
  }
56
- function parseDeviceCodeTokenResponse(payload) {
51
+ function parseStringArray(value) {
52
+ if (!Array.isArray(value)) {
53
+ return null;
54
+ }
55
+ const strings = value.filter((item) => typeof item === 'string');
56
+ return strings.length === value.length ? strings : null;
57
+ }
58
+ function parseDeviceCodeApiKeyResponse(payload) {
57
59
  if (typeof payload !== 'object' || payload === null) {
58
60
  return null;
59
61
  }
60
- const accessToken = parseString(Reflect.get(payload, 'accessToken')) ??
61
- parseString(Reflect.get(payload, 'access_token'));
62
- if (!accessToken) {
62
+ const status = parseString(Reflect.get(payload, 'status'));
63
+ if (status !== 'approved') {
63
64
  return null;
64
65
  }
65
- const refreshToken = parseString(Reflect.get(payload, 'refreshToken')) ??
66
- parseString(Reflect.get(payload, 'refresh_token'));
67
- const expiresIn = parseNumber(Reflect.get(payload, 'expiresIn')) ??
68
- parseNumber(Reflect.get(payload, 'expires_in'));
69
- const expiresAt = parseNumber(Reflect.get(payload, 'expiresAt')) ??
70
- parseNumber(Reflect.get(payload, 'expires_at'));
66
+ const fullKey = parseString(Reflect.get(payload, 'fullKey'));
67
+ const apiKey = Reflect.get(payload, 'apiKey');
68
+ if (!fullKey || typeof apiKey !== 'object' || apiKey === null) {
69
+ throw new Error('Device login approved response missing API key fields');
70
+ }
71
+ const id = parseString(Reflect.get(apiKey, 'id'));
72
+ const keyDisplay = parseString(Reflect.get(apiKey, 'keyDisplay'));
73
+ const name = parseString(Reflect.get(apiKey, 'name'));
74
+ const scopes = parseStringArray(Reflect.get(apiKey, 'scopes'));
75
+ const keyStatus = parseString(Reflect.get(apiKey, 'status'));
76
+ if (!id || !keyDisplay || !name || !scopes || !keyStatus) {
77
+ throw new Error('Device login approved response missing API key fields');
78
+ }
71
79
  return {
72
- accessToken,
73
- refreshToken,
74
- expiresIn,
75
- expiresAt,
80
+ id,
81
+ keyDisplay,
82
+ name,
83
+ scopes,
84
+ status: keyStatus,
85
+ fullKey,
76
86
  };
77
87
  }
78
88
  function parseDeviceErrorCode(payload) {
@@ -81,11 +91,6 @@ function parseDeviceErrorCode(payload) {
81
91
  }
82
92
  return parseString(Reflect.get(payload, 'error'));
83
93
  }
84
- function isTransientDevicePollErrorCode(errorCode) {
85
- return (errorCode === 'server_error' ||
86
- errorCode === 'temporary_unavailable' ||
87
- errorCode === 'temporarily_unavailable');
88
- }
89
94
  function parseSupabaseUser(payload) {
90
95
  if (typeof payload !== 'object' || payload === null) {
91
96
  return null;
@@ -533,7 +538,7 @@ export class DextoApiClient {
533
538
  headers: {
534
539
  'Content-Type': 'application/json',
535
540
  },
536
- body: JSON.stringify({ device_code: deviceCode }),
541
+ body: JSON.stringify({ deviceCode }),
537
542
  signal: this.createRequestSignal(options.signal),
538
543
  });
539
544
  }
@@ -554,52 +559,25 @@ export class DextoApiClient {
554
559
  if (response.status === 429) {
555
560
  return { status: 'slowDown' };
556
561
  }
557
- const errorCode = parseDeviceErrorCode(payload);
558
- if (errorCode === 'authorization_pending') {
559
- return { status: 'pending' };
560
- }
561
- if (errorCode === 'slow_down') {
562
- return { status: 'slowDown' };
563
- }
564
- if (errorCode === 'expired_token') {
565
- return { status: 'expired' };
566
- }
567
- if (errorCode === 'access_denied') {
568
- return { status: 'denied' };
569
- }
570
- if (errorCode && isTransientDevicePollErrorCode(errorCode)) {
571
- return { status: 'transientError' };
572
- }
573
562
  if (response.status >= 500) {
574
563
  return { status: 'transientError' };
575
564
  }
565
+ const errorCode = parseDeviceErrorCode(payload);
576
566
  if (errorCode) {
577
567
  throw new Error(`Device login failed: ${errorCode}`);
578
568
  }
579
569
  throw new Error(`Device login polling failed with status ${response.status}`);
580
570
  }
581
- const token = parseDeviceCodeTokenResponse(payload);
582
- if (token) {
571
+ const apiKey = parseDeviceCodeApiKeyResponse(payload);
572
+ if (apiKey) {
583
573
  return {
584
- status: 'success',
585
- token,
574
+ status: 'approved',
575
+ apiKey,
586
576
  };
587
577
  }
588
578
  const errorCode = parseDeviceErrorCode(payload);
589
- if (errorCode === 'authorization_pending') {
590
- return { status: 'pending' };
591
- }
592
- if (errorCode === 'slow_down') {
593
- return { status: 'slowDown' };
594
- }
595
- if (errorCode === 'expired_token') {
596
- return { status: 'expired' };
597
- }
598
- if (errorCode === 'access_denied') {
599
- return { status: 'denied' };
600
- }
601
- if (errorCode && isTransientDevicePollErrorCode(errorCode)) {
602
- return { status: 'transientError' };
579
+ if (errorCode) {
580
+ throw new Error(`Device login failed: ${errorCode}`);
603
581
  }
604
582
  return { status: 'pending' };
605
583
  }
@@ -1,4 +1,4 @@
1
- import type { AuthLoginResult } from './types.js';
1
+ import type { DeviceApiKeyLoginResult } from './types.js';
2
2
  export interface DeviceLoginPrompt {
3
3
  userCode: string;
4
4
  verificationUrl: string;
@@ -10,5 +10,5 @@ export interface DeviceLoginOptionsInput {
10
10
  signal?: AbortSignal | undefined;
11
11
  onPrompt?: ((prompt: DeviceLoginPrompt) => void | Promise<void>) | undefined;
12
12
  }
13
- export declare function performDeviceCodeLogin(optionsInput?: DeviceLoginOptionsInput): Promise<AuthLoginResult>;
13
+ export declare function performDeviceCodeLogin(optionsInput?: DeviceLoginOptionsInput): Promise<DeviceApiKeyLoginResult>;
14
14
  //# sourceMappingURL=device.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"device.d.ts","sourceRoot":"","sources":["../../../src/cli/auth/device.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAKlD,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,uBAAuB,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;CAChF;AAoDD,wBAAsB,sBAAsB,CACxC,YAAY,GAAE,uBAA4B,GAC3C,OAAO,CAAC,eAAe,CAAC,CAqE1B"}
1
+ {"version":3,"file":"device.d.ts","sourceRoot":"","sources":["../../../src/cli/auth/device.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAI1D,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,uBAAuB,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;CAChF;AAoDD,wBAAsB,sBAAsB,CACxC,YAAY,GAAE,uBAA4B,GAC3C,OAAO,CAAC,uBAAuB,CAAC,CA0DlC"}
@@ -74,19 +74,10 @@ export async function performDeviceCodeLogin(optionsInput = {}) {
74
74
  if (pollResult.status === 'denied') {
75
75
  throw new Error('Device login was denied.');
76
76
  }
77
- const tokenResponse = pollResult.token;
78
- const computedExpiresIn = tokenResponse.expiresIn ??
79
- (tokenResponse.expiresAt
80
- ? Math.max(0, tokenResponse.expiresAt - Date.now() / 1000)
81
- : undefined);
82
- const user = await authClient.fetchSupabaseUser(tokenResponse.accessToken, {
83
- signal: options.signal ?? undefined,
84
- });
85
77
  return {
86
- accessToken: tokenResponse.accessToken,
87
- refreshToken: tokenResponse.refreshToken ?? undefined,
88
- expiresIn: computedExpiresIn,
89
- user,
78
+ dextoApiKey: pollResult.apiKey.fullKey,
79
+ dextoKeyId: pollResult.apiKey.id,
80
+ dextoKeyDisplay: pollResult.apiKey.keyDisplay,
90
81
  };
91
82
  }
92
83
  throw new Error('Device login timed out. Please restart login.');
@@ -1,7 +1,8 @@
1
1
  export { type AuthConfig, storeAuth, loadAuth, removeAuth, isAuthenticated, getAuthToken, getAuthTokenQuietly, getDextoApiKey, getAuthFilePath, } from './service.js';
2
2
  export { type OAuthResult } from './oauth.js';
3
+ export { type DeviceApiKeyLoginResult } from './types.js';
3
4
  export { type DeviceLoginPrompt, performDeviceCodeLogin } from './device.js';
4
- export { type PersistOAuthLoginOptions, type PersistedLoginResult, persistOAuthLoginResult, } from './login-persistence.js';
5
+ export { type PersistOAuthLoginOptions, type PersistedLoginResult, persistDeviceApiKeyLoginResult, persistOAuthLoginResult, } from './login-persistence.js';
5
6
  export { type UsageSummaryResponse, DextoApiClient, getDextoApiClient } from './api-client.js';
6
7
  export { SUPABASE_URL, SUPABASE_ANON_KEY, DEXTO_API_URL, DEXTO_PLATFORM_URL } from './constants.js';
7
8
  export { buildDextoBillingUrl, getBillingBalanceForCurrentLogin, createBillingCheckoutForCurrentLogin, openDextoBillingPage, } from './billing.js';
@@ -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,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
+ {"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,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,KAAK,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAE7E,OAAO,EACH,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,8BAA8B,EAC9B,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"}
@@ -2,7 +2,7 @@
2
2
  // Public exports for auth module
3
3
  export { storeAuth, loadAuth, removeAuth, isAuthenticated, getAuthToken, getAuthTokenQuietly, getDextoApiKey, getAuthFilePath, } from './service.js';
4
4
  export { performDeviceCodeLogin } from './device.js';
5
- export { persistOAuthLoginResult, } from './login-persistence.js';
5
+ export { persistDeviceApiKeyLoginResult, 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
8
  export { buildDextoBillingUrl, getBillingBalanceForCurrentLogin, createBillingCheckoutForCurrentLogin, openDextoBillingPage, } from './billing.js';
@@ -1,5 +1,6 @@
1
1
  import { type DextoApiKeyProvisionStatus } from './dexto-api-key.js';
2
2
  import type { OAuthResult } from './oauth.js';
3
+ import type { DeviceApiKeyLoginResult } from './types.js';
3
4
  export interface PersistOAuthLoginOptions {
4
5
  onProvisionStatus?: ((status: DextoApiKeyProvisionStatus) => void) | undefined;
5
6
  }
@@ -10,4 +11,5 @@ export interface PersistedLoginResult {
10
11
  hasDextoApiKey: boolean;
11
12
  }
12
13
  export declare function persistOAuthLoginResult(result: OAuthResult, options?: PersistOAuthLoginOptions): Promise<PersistedLoginResult>;
14
+ export declare function persistDeviceApiKeyLoginResult(result: DeviceApiKeyLoginResult): Promise<PersistedLoginResult>;
13
15
  //# sourceMappingURL=login-persistence.d.ts.map
@@ -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;AA4CD,wBAAsB,uBAAuB,CACzC,MAAM,EAAE,WAAW,EACnB,OAAO,GAAE,wBAA6B,GACvC,OAAO,CAAC,oBAAoB,CAAC,CAyB/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;AAE9C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAE1D,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;AAED,wBAAsB,8BAA8B,CAChD,MAAM,EAAE,uBAAuB,GAChC,OAAO,CAAC,oBAAoB,CAAC,CAY/B"}
@@ -50,3 +50,15 @@ export async function persistOAuthLoginResult(result, options = {}) {
50
50
  hasDextoApiKey: Boolean(ensured?.dextoApiKey ?? preservedDextoApiKey?.dextoApiKey),
51
51
  };
52
52
  }
53
+ export async function persistDeviceApiKeyLoginResult(result) {
54
+ await storeAuth({
55
+ dextoApiKey: result.dextoApiKey,
56
+ dextoKeyId: result.dextoKeyId,
57
+ dextoApiKeySource: 'provisioned',
58
+ createdAt: Date.now(),
59
+ });
60
+ return {
61
+ keyId: result.dextoKeyId,
62
+ hasDextoApiKey: true,
63
+ };
64
+ }
@@ -3,10 +3,9 @@ export interface AuthenticatedUser {
3
3
  email: string;
4
4
  name?: string | undefined;
5
5
  }
6
- export interface AuthLoginResult {
7
- accessToken: string;
8
- refreshToken?: string | undefined;
9
- expiresIn?: number | undefined;
10
- user?: AuthenticatedUser | undefined;
6
+ export interface DeviceApiKeyLoginResult {
7
+ dextoApiKey: string;
8
+ dextoKeyId: string;
9
+ dextoKeyDisplay: string;
11
10
  }
12
11
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/cli/auth/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED,MAAM,WAAW,eAAe;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,IAAI,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;CACxC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/cli/auth/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED,MAAM,WAAW,uBAAuB;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;CAC3B"}
@@ -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,CAuhBlB;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,CAimBlB;AAED,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBxF"}
@@ -240,7 +240,8 @@ export function createCloudAgentBackend(client, cloudAgentId) {
240
240
  const sessionMetadataCache = new Map();
241
241
  const sessionTitleCache = new Map();
242
242
  const sessionModelCache = new Map();
243
- const queueBySession = new Map();
243
+ const steerQueueBySession = new Map();
244
+ const followUpQueueBySession = new Map();
244
245
  const globalDisabledTools = [];
245
246
  const sessionDisabledTools = new Map();
246
247
  const sessionAutoApproveTools = new Map();
@@ -293,17 +294,46 @@ export function createCloudAgentBackend(client, cloudAgentId) {
293
294
  }
294
295
  return history;
295
296
  };
296
- const dequeueQueuedMessages = (sessionId) => {
297
+ const dequeueQueuedMessages = (queueBySession, sessionId) => {
297
298
  const queued = queueBySession.get(sessionId) ?? [];
298
299
  queueBySession.delete(sessionId);
299
300
  return queued;
300
301
  };
301
- const appendQueuedMessage = (sessionId, message) => {
302
+ const appendQueuedMessage = (queueBySession, sessionId, message) => {
302
303
  const current = queueBySession.get(sessionId) ?? [];
303
304
  const next = [...current, message];
304
305
  queueBySession.set(sessionId, next);
305
306
  return next.length;
306
307
  };
308
+ const removeQueuedMessage = (queueBySession, queueKind, sessionId, messageId) => {
309
+ const current = queueBySession.get(sessionId) ?? [];
310
+ const next = current.filter((message) => message.id !== messageId);
311
+ if (next.length === current.length) {
312
+ return false;
313
+ }
314
+ queueBySession.set(sessionId, next);
315
+ eventBus.emit('message:removed', {
316
+ id: messageId,
317
+ queue: queueKind,
318
+ sessionId,
319
+ });
320
+ return true;
321
+ };
322
+ const clearQueuedMessages = (queueBySession, sessionId) => {
323
+ const clearedCount = (queueBySession.get(sessionId) ?? []).length;
324
+ queueBySession.delete(sessionId);
325
+ return clearedCount;
326
+ };
327
+ const dequeueNextSessionMessages = (sessionId) => {
328
+ const steerMessages = dequeueQueuedMessages(steerQueueBySession, sessionId);
329
+ if (steerMessages.length > 0) {
330
+ return steerMessages;
331
+ }
332
+ return dequeueQueuedMessages(followUpQueueBySession, sessionId);
333
+ };
334
+ const getNextSessionQueueKind = (sessionId) => {
335
+ return (steerQueueBySession.get(sessionId) ?? []).length > 0 ? 'steer' : 'follow-up';
336
+ };
307
337
  const currentLLMConfig = (sessionId) => {
308
338
  const cachedModel = sessionId ? sessionModelCache.get(sessionId) : undefined;
309
339
  return {
@@ -414,7 +444,8 @@ export function createCloudAgentBackend(client, cloudAgentId) {
414
444
  emitStreamingEvent(eventBus, event);
415
445
  yield event;
416
446
  }
417
- const queuedMessages = dequeueQueuedMessages(sessionId);
447
+ const queueKind = getNextSessionQueueKind(sessionId);
448
+ const queuedMessages = dequeueNextSessionMessages(sessionId);
418
449
  if (queuedMessages.length === 0) {
419
450
  if (pendingRunComplete) {
420
451
  emitStreamingEvent(eventBus, pendingRunComplete);
@@ -428,6 +459,7 @@ export function createCloudAgentBackend(client, cloudAgentId) {
428
459
  sessionId,
429
460
  count: queuedMessages.length,
430
461
  ids: queuedMessages.map((message) => message.id),
462
+ queue: queueKind,
431
463
  coalesced: queuedMessages.length > 1,
432
464
  content: combinedContent,
433
465
  messages: queuedMessages,
@@ -515,19 +547,22 @@ export function createCloudAgentBackend(client, cloudAgentId) {
515
547
  }),
516
548
  clearContext: (async (sessionId) => {
517
549
  await client.clearCloudAgentSessionContext(cloudAgentId, sessionId);
518
- queueBySession.delete(sessionId);
550
+ steerQueueBySession.delete(sessionId);
551
+ followUpQueueBySession.delete(sessionId);
519
552
  eventBus.emit('context:cleared', { sessionId });
520
553
  }),
521
554
  compactContext: (async () => {
522
555
  throw unsupportedCloudFeature('Context compaction');
523
556
  }),
524
- queueMessage: (async (sessionId, input) => {
557
+ steer: (async (sessionId, input) => {
558
+ contentPartsToCloudText(input.content);
525
559
  const messageId = `queued-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
526
560
  const message = buildQueuedMessage(messageId, [...input.content]);
527
- const position = appendQueuedMessage(sessionId, message);
561
+ const position = appendQueuedMessage(steerQueueBySession, sessionId, message);
528
562
  eventBus.emit('message:queued', {
529
563
  id: message.id,
530
564
  position,
565
+ queue: 'steer',
531
566
  sessionId,
532
567
  });
533
568
  return {
@@ -536,26 +571,32 @@ export function createCloudAgentBackend(client, cloudAgentId) {
536
571
  id: message.id,
537
572
  };
538
573
  }),
539
- getQueuedMessages: (async (sessionId) => queueBySession.get(sessionId) ?? []),
540
- removeQueuedMessage: (async (sessionId, messageId) => {
541
- const current = queueBySession.get(sessionId) ?? [];
542
- const next = current.filter((message) => message.id !== messageId);
543
- queueBySession.set(sessionId, next);
544
- eventBus.emit('message:removed', {
545
- id: messageId,
574
+ followUp: (async (sessionId, input) => {
575
+ contentPartsToCloudText(input.content);
576
+ const messageId = `queued-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
577
+ const message = buildQueuedMessage(messageId, [...input.content]);
578
+ const position = appendQueuedMessage(followUpQueueBySession, sessionId, message);
579
+ eventBus.emit('message:queued', {
580
+ id: message.id,
581
+ position,
582
+ queue: 'follow-up',
546
583
  sessionId,
547
584
  });
548
- return true;
585
+ return {
586
+ queued: true,
587
+ position,
588
+ id: message.id,
589
+ };
549
590
  }),
550
- clearMessageQueue: (async (sessionId) => {
551
- if (typeof sessionId === 'string') {
552
- const clearedCount = (queueBySession.get(sessionId) ?? []).length;
553
- queueBySession.delete(sessionId);
554
- return clearedCount;
555
- }
556
- const clearedCount = Array.from(queueBySession.values()).reduce((total, queuedMessages) => total + queuedMessages.length, 0);
557
- queueBySession.clear();
558
- return clearedCount;
591
+ getSteerMessages: (async (sessionId) => steerQueueBySession.get(sessionId) ?? []),
592
+ getFollowUpMessages: (async (sessionId) => followUpQueueBySession.get(sessionId) ?? []),
593
+ removeSteerMessage: (async (sessionId, messageId) => removeQueuedMessage(steerQueueBySession, 'steer', sessionId, messageId)),
594
+ removeFollowUpMessage: (async (sessionId, messageId) => removeQueuedMessage(followUpQueueBySession, 'follow-up', sessionId, messageId)),
595
+ clearSteerQueue: (async (sessionId) => {
596
+ return clearQueuedMessages(steerQueueBySession, sessionId);
597
+ }),
598
+ clearFollowUpQueue: (async (sessionId) => {
599
+ return clearQueuedMessages(followUpQueueBySession, sessionId);
559
600
  }),
560
601
  cancel: (async (sessionId) => {
561
602
  await client.cancelCloudAgentSessionRun(cloudAgentId, sessionId);
@@ -1,9 +1,12 @@
1
1
  export interface LoginCommandOptions {
2
2
  apiKey?: string;
3
3
  token?: string;
4
+ platformUrl?: string | undefined;
4
5
  interactive?: boolean;
5
6
  }
6
7
  export declare function handleLoginCommand(options?: LoginCommandOptions): Promise<void>;
7
8
  export declare function handleAutoLogin(): Promise<void>;
8
- export declare function handleDeviceLogin(): Promise<void>;
9
+ export declare function handleDeviceLogin(options?: {
10
+ platformUrl?: string;
11
+ }): Promise<void>;
9
12
  //# sourceMappingURL=login.d.ts.map
@@ -1 +1 @@
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
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/auth/login.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,mBAAmB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB;AAgBD,wBAAsB,kBAAkB,CAAC,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmEzF;AAGD,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAErD;AAED,wBAAsB,iBAAiB,CAAC,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CA4B7F"}
@@ -1,7 +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, } from '../../auth/index.js';
4
+ import { getDextoApiClient, isAuthenticated, loadAuth, performDeviceCodeLogin, persistDeviceApiKeyLoginResult, persistOAuthLoginResult, storeAuth, } from '../../auth/index.js';
5
5
  function isCancellationError(errorMessage) {
6
6
  const lower = errorMessage.toLowerCase();
7
7
  return (lower.includes('canceled') ||
@@ -58,12 +58,12 @@ export async function handleLoginCommand(options = {}) {
58
58
  return;
59
59
  }
60
60
  if (options.interactive === false) {
61
- await handleDeviceLogin();
61
+ await handleDeviceLogin(options.platformUrl ? { platformUrl: options.platformUrl } : {});
62
62
  console.log(chalk.green('🎉 Login successful!'));
63
63
  return;
64
64
  }
65
65
  p.intro(chalk.inverse(' Login to Dexto '));
66
- await handleDeviceLogin();
66
+ await handleDeviceLogin(options.platformUrl ? { platformUrl: options.platformUrl } : {});
67
67
  p.outro(chalk.green('🎉 Login successful!'));
68
68
  }
69
69
  catch (error) {
@@ -76,9 +76,10 @@ export async function handleLoginCommand(options = {}) {
76
76
  export async function handleAutoLogin() {
77
77
  await handleDeviceLogin();
78
78
  }
79
- export async function handleDeviceLogin() {
79
+ export async function handleDeviceLogin(options = {}) {
80
80
  try {
81
81
  const result = await performDeviceCodeLogin({
82
+ ...(options.platformUrl ? { apiUrl: options.platformUrl } : {}),
82
83
  onPrompt: (prompt) => {
83
84
  console.log(chalk.cyan('\nUse any browser to complete login:'));
84
85
  if (prompt.verificationUrlComplete) {
@@ -92,10 +93,8 @@ export async function handleDeviceLogin() {
92
93
  console.log(chalk.dim(` • Code expires in ~${Math.ceil(prompt.expiresIn / 60)} min`));
93
94
  },
94
95
  });
95
- const persisted = await persistOAuthLoginResult(result);
96
- if (persisted.email) {
97
- console.log(chalk.dim(`\nWelcome back, ${persisted.email}`));
98
- }
96
+ const persisted = await persistDeviceApiKeyLoginResult(result);
97
+ console.log(chalk.dim(`\nSaved Dexto API key ${persisted.keyId ?? ''}`.trim()));
99
98
  }
100
99
  catch (error) {
101
100
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -1 +1 @@
1
- {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/auth/register.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,wBAAwB,CAAC;AAE5E,wBAAgB,mBAAmB,CAAC,EAAE,OAAO,EAAE,EAAE,6BAA6B,GAAG,IAAI,CA0GpF"}
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/auth/register.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,wBAAwB,CAAC;AAE5E,wBAAgB,mBAAmB,CAAC,EAAE,OAAO,EAAE,EAAE,6BAA6B,GAAG,IAAI,CAsHpF"}