dexto 1.5.5 → 1.5.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/README.md +13 -0
  2. package/dist/agents/agent-template.yml +1 -1
  3. package/dist/agents/coding-agent/coding-agent.yml +17 -2
  4. package/dist/agents/coding-agent/skills/code-review.md +46 -0
  5. package/dist/agents/explore-agent/explore-agent.yml +2 -0
  6. package/dist/agents/podcast-agent/podcast-agent.yml +1 -1
  7. package/dist/analytics/events.d.ts +1 -1
  8. package/dist/analytics/events.d.ts.map +1 -1
  9. package/dist/api/server-hono.d.ts.map +1 -1
  10. package/dist/api/server-hono.js +55 -10
  11. package/dist/cli/assets/dexto-logo.svg +31 -0
  12. package/dist/cli/auth/api-client.d.ts +49 -0
  13. package/dist/cli/auth/api-client.d.ts.map +1 -0
  14. package/dist/cli/auth/api-client.js +127 -0
  15. package/dist/cli/auth/constants.d.ts +23 -0
  16. package/dist/cli/auth/constants.d.ts.map +1 -0
  17. package/dist/cli/auth/constants.js +24 -0
  18. package/dist/cli/auth/index.d.ts +5 -0
  19. package/dist/cli/auth/index.d.ts.map +1 -0
  20. package/dist/cli/auth/index.js +6 -0
  21. package/dist/cli/auth/oauth.d.ts +26 -0
  22. package/dist/cli/auth/oauth.d.ts.map +1 -0
  23. package/dist/cli/auth/oauth.js +327 -0
  24. package/dist/cli/auth/service.d.ts +20 -0
  25. package/dist/cli/auth/service.d.ts.map +1 -0
  26. package/dist/cli/auth/service.js +147 -0
  27. package/dist/cli/commands/auth/index.d.ts +4 -0
  28. package/dist/cli/commands/auth/index.d.ts.map +1 -0
  29. package/dist/cli/commands/auth/index.js +4 -0
  30. package/dist/cli/commands/auth/login.d.ts +9 -0
  31. package/dist/cli/commands/auth/login.d.ts.map +1 -0
  32. package/dist/cli/commands/auth/login.js +255 -0
  33. package/dist/cli/commands/auth/logout.d.ts +5 -0
  34. package/dist/cli/commands/auth/logout.d.ts.map +1 -0
  35. package/dist/cli/commands/auth/logout.js +51 -0
  36. package/dist/cli/commands/auth/status.d.ts +2 -0
  37. package/dist/cli/commands/auth/status.d.ts.map +1 -0
  38. package/dist/cli/commands/auth/status.js +22 -0
  39. package/dist/cli/commands/billing/index.d.ts +2 -0
  40. package/dist/cli/commands/billing/index.d.ts.map +1 -0
  41. package/dist/cli/commands/billing/index.js +2 -0
  42. package/dist/cli/commands/billing/status.d.ts +6 -0
  43. package/dist/cli/commands/billing/status.d.ts.map +1 -0
  44. package/dist/cli/commands/billing/status.js +60 -0
  45. package/dist/cli/commands/index.d.ts +4 -0
  46. package/dist/cli/commands/index.d.ts.map +1 -1
  47. package/dist/cli/commands/index.js +9 -0
  48. package/dist/cli/commands/interactive-commands/auth/index.d.ts +12 -0
  49. package/dist/cli/commands/interactive-commands/auth/index.d.ts.map +1 -0
  50. package/dist/cli/commands/interactive-commands/auth/index.js +20 -0
  51. package/dist/cli/commands/interactive-commands/command-parser.d.ts +5 -0
  52. package/dist/cli/commands/interactive-commands/command-parser.d.ts.map +1 -1
  53. package/dist/cli/commands/interactive-commands/command-parser.js +6 -0
  54. package/dist/cli/commands/interactive-commands/commands.d.ts +1 -0
  55. package/dist/cli/commands/interactive-commands/commands.d.ts.map +1 -1
  56. package/dist/cli/commands/interactive-commands/commands.js +10 -0
  57. package/dist/cli/commands/interactive-commands/export/index.d.ts +13 -0
  58. package/dist/cli/commands/interactive-commands/export/index.d.ts.map +1 -0
  59. package/dist/cli/commands/interactive-commands/export/index.js +21 -0
  60. package/dist/cli/commands/interactive-commands/general-commands.d.ts.map +1 -1
  61. package/dist/cli/commands/interactive-commands/general-commands.js +1 -0
  62. package/dist/cli/commands/interactive-commands/mcp/index.d.ts +2 -2
  63. package/dist/cli/commands/interactive-commands/mcp/index.d.ts.map +1 -1
  64. package/dist/cli/commands/interactive-commands/mcp/index.js +4 -7
  65. package/dist/cli/commands/interactive-commands/model/index.d.ts +2 -2
  66. package/dist/cli/commands/interactive-commands/model/index.d.ts.map +1 -1
  67. package/dist/cli/commands/interactive-commands/model/index.js +4 -7
  68. package/dist/cli/commands/interactive-commands/plugin/index.d.ts +13 -0
  69. package/dist/cli/commands/interactive-commands/plugin/index.d.ts.map +1 -0
  70. package/dist/cli/commands/interactive-commands/plugin/index.js +18 -0
  71. package/dist/cli/commands/interactive-commands/prompt-commands.d.ts +3 -1
  72. package/dist/cli/commands/interactive-commands/prompt-commands.d.ts.map +1 -1
  73. package/dist/cli/commands/interactive-commands/prompt-commands.js +72 -36
  74. package/dist/cli/commands/interactive-commands/system/system-commands.d.ts.map +1 -1
  75. package/dist/cli/commands/interactive-commands/system/system-commands.js +2 -3
  76. package/dist/cli/commands/plugin.d.ts +161 -0
  77. package/dist/cli/commands/plugin.d.ts.map +1 -0
  78. package/dist/cli/commands/plugin.js +376 -0
  79. package/dist/cli/commands/setup.d.ts +9 -9
  80. package/dist/cli/commands/setup.d.ts.map +1 -1
  81. package/dist/cli/commands/setup.js +325 -37
  82. package/dist/cli/commands/sync-agents.d.ts +44 -0
  83. package/dist/cli/commands/sync-agents.d.ts.map +1 -0
  84. package/dist/cli/commands/sync-agents.js +483 -0
  85. package/dist/cli/ink-cli/InkCLIRefactored.d.ts +14 -1
  86. package/dist/cli/ink-cli/InkCLIRefactored.d.ts.map +1 -1
  87. package/dist/cli/ink-cli/InkCLIRefactored.js +8 -2
  88. package/dist/cli/ink-cli/components/ApprovalPrompt.d.ts +1 -1
  89. package/dist/cli/ink-cli/components/ApprovalPrompt.d.ts.map +1 -1
  90. package/dist/cli/ink-cli/components/ApprovalPrompt.js +80 -12
  91. package/dist/cli/ink-cli/components/Footer.d.ts +2 -1
  92. package/dist/cli/ink-cli/components/Footer.d.ts.map +1 -1
  93. package/dist/cli/ink-cli/components/Footer.js +6 -2
  94. package/dist/cli/ink-cli/components/SlashCommandAutocomplete.d.ts.map +1 -1
  95. package/dist/cli/ink-cli/components/SlashCommandAutocomplete.js +15 -7
  96. package/dist/cli/ink-cli/components/StatusBar.d.ts +9 -1
  97. package/dist/cli/ink-cli/components/StatusBar.d.ts.map +1 -1
  98. package/dist/cli/ink-cli/components/StatusBar.js +17 -5
  99. package/dist/cli/ink-cli/components/TodoPanel.d.ts +11 -8
  100. package/dist/cli/ink-cli/components/TodoPanel.d.ts.map +1 -1
  101. package/dist/cli/ink-cli/components/TodoPanel.js +38 -36
  102. package/dist/cli/ink-cli/components/chat/Header.d.ts.map +1 -1
  103. package/dist/cli/ink-cli/components/chat/Header.js +1 -1
  104. package/dist/cli/ink-cli/components/chat/MessageItem.d.ts.map +1 -1
  105. package/dist/cli/ink-cli/components/chat/MessageItem.js +14 -1
  106. package/dist/cli/ink-cli/components/chat/styled-boxes/LogConfigBox.js +1 -1
  107. package/dist/cli/ink-cli/components/modes/AlternateBufferCLI.d.ts.map +1 -1
  108. package/dist/cli/ink-cli/components/modes/AlternateBufferCLI.js +16 -4
  109. package/dist/cli/ink-cli/components/modes/StaticCLI.d.ts.map +1 -1
  110. package/dist/cli/ink-cli/components/modes/StaticCLI.js +4 -1
  111. package/dist/cli/ink-cli/components/overlays/ExportWizard.d.ts +22 -0
  112. package/dist/cli/ink-cli/components/overlays/ExportWizard.d.ts.map +1 -0
  113. package/dist/cli/ink-cli/components/overlays/ExportWizard.js +308 -0
  114. package/dist/cli/ink-cli/components/overlays/LogLevelSelector.d.ts +1 -0
  115. package/dist/cli/ink-cli/components/overlays/LogLevelSelector.d.ts.map +1 -1
  116. package/dist/cli/ink-cli/components/overlays/LogLevelSelector.js +31 -20
  117. package/dist/cli/ink-cli/components/overlays/MarketplaceAddPrompt.d.ts +20 -0
  118. package/dist/cli/ink-cli/components/overlays/MarketplaceAddPrompt.d.ts.map +1 -0
  119. package/dist/cli/ink-cli/components/overlays/MarketplaceAddPrompt.js +81 -0
  120. package/dist/cli/ink-cli/components/overlays/MarketplaceBrowser.d.ts +31 -0
  121. package/dist/cli/ink-cli/components/overlays/MarketplaceBrowser.d.ts.map +1 -0
  122. package/dist/cli/ink-cli/components/overlays/MarketplaceBrowser.js +297 -0
  123. package/dist/cli/ink-cli/components/overlays/McpRemoveSelector.d.ts.map +1 -1
  124. package/dist/cli/ink-cli/components/overlays/McpRemoveSelector.js +7 -1
  125. package/dist/cli/ink-cli/components/overlays/McpServerActions.d.ts +1 -1
  126. package/dist/cli/ink-cli/components/overlays/McpServerActions.d.ts.map +1 -1
  127. package/dist/cli/ink-cli/components/overlays/McpServerActions.js +9 -0
  128. package/dist/cli/ink-cli/components/overlays/McpServerList.d.ts.map +1 -1
  129. package/dist/cli/ink-cli/components/overlays/McpServerList.js +9 -2
  130. package/dist/cli/ink-cli/components/overlays/ModelSelectorRefactored.d.ts.map +1 -1
  131. package/dist/cli/ink-cli/components/overlays/ModelSelectorRefactored.js +15 -2
  132. package/dist/cli/ink-cli/components/overlays/PluginActions.d.ts +27 -0
  133. package/dist/cli/ink-cli/components/overlays/PluginActions.d.ts.map +1 -0
  134. package/dist/cli/ink-cli/components/overlays/PluginActions.js +66 -0
  135. package/dist/cli/ink-cli/components/overlays/PluginList.d.ts +21 -0
  136. package/dist/cli/ink-cli/components/overlays/PluginList.d.ts.map +1 -0
  137. package/dist/cli/ink-cli/components/overlays/PluginList.js +70 -0
  138. package/dist/cli/ink-cli/components/overlays/PluginManager.d.ts +21 -0
  139. package/dist/cli/ink-cli/components/overlays/PluginManager.d.ts.map +1 -0
  140. package/dist/cli/ink-cli/components/overlays/PluginManager.js +63 -0
  141. package/dist/cli/ink-cli/components/overlays/PromptList.d.ts.map +1 -1
  142. package/dist/cli/ink-cli/components/overlays/PromptList.js +4 -1
  143. package/dist/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.d.ts +2 -1
  144. package/dist/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.d.ts.map +1 -1
  145. package/dist/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.js +61 -2
  146. package/dist/cli/ink-cli/components/renderers/FilePreviewRenderer.d.ts +4 -2
  147. package/dist/cli/ink-cli/components/renderers/FilePreviewRenderer.d.ts.map +1 -1
  148. package/dist/cli/ink-cli/components/renderers/FilePreviewRenderer.js +4 -4
  149. package/dist/cli/ink-cli/constants/tips.js +2 -2
  150. package/dist/cli/ink-cli/containers/InputContainer.d.ts.map +1 -1
  151. package/dist/cli/ink-cli/containers/InputContainer.js +31 -3
  152. package/dist/cli/ink-cli/containers/OverlayContainer.d.ts.map +1 -1
  153. package/dist/cli/ink-cli/containers/OverlayContainer.js +260 -11
  154. package/dist/cli/ink-cli/hooks/index.d.ts +1 -0
  155. package/dist/cli/ink-cli/hooks/index.d.ts.map +1 -1
  156. package/dist/cli/ink-cli/hooks/index.js +1 -0
  157. package/dist/cli/ink-cli/hooks/useCLIState.d.ts.map +1 -1
  158. package/dist/cli/ink-cli/hooks/useCLIState.js +3 -0
  159. package/dist/cli/ink-cli/hooks/useGitBranch.d.ts +13 -0
  160. package/dist/cli/ink-cli/hooks/useGitBranch.d.ts.map +1 -0
  161. package/dist/cli/ink-cli/hooks/useGitBranch.js +35 -0
  162. package/dist/cli/ink-cli/hooks/useInputOrchestrator.d.ts.map +1 -1
  163. package/dist/cli/ink-cli/hooks/useInputOrchestrator.js +50 -6
  164. package/dist/cli/ink-cli/services/processStream.d.ts.map +1 -1
  165. package/dist/cli/ink-cli/services/processStream.js +42 -10
  166. package/dist/cli/ink-cli/state/initialState.d.ts.map +1 -1
  167. package/dist/cli/ink-cli/state/initialState.js +3 -0
  168. package/dist/cli/ink-cli/state/types.d.ts +16 -1
  169. package/dist/cli/ink-cli/state/types.d.ts.map +1 -1
  170. package/dist/cli/ink-cli/utils/commandOverlays.d.ts.map +1 -1
  171. package/dist/cli/ink-cli/utils/commandOverlays.js +2 -0
  172. package/dist/cli/ink-cli/utils/messageFormatting.d.ts +14 -1
  173. package/dist/cli/ink-cli/utils/messageFormatting.d.ts.map +1 -1
  174. package/dist/cli/ink-cli/utils/messageFormatting.js +68 -8
  175. package/dist/cli/ink-cli/utils/toolUtils.d.ts +11 -0
  176. package/dist/cli/ink-cli/utils/toolUtils.d.ts.map +1 -1
  177. package/dist/cli/ink-cli/utils/toolUtils.js +17 -0
  178. package/dist/cli/mcp/index.d.ts +8 -0
  179. package/dist/cli/mcp/index.d.ts.map +1 -0
  180. package/dist/cli/mcp/index.js +7 -0
  181. package/dist/cli/mcp/oauth-factory.d.ts +6 -0
  182. package/dist/cli/mcp/oauth-factory.d.ts.map +1 -0
  183. package/dist/cli/mcp/oauth-factory.js +25 -0
  184. package/dist/cli/mcp/oauth-provider.d.ts +10 -0
  185. package/dist/cli/mcp/oauth-provider.d.ts.map +1 -0
  186. package/dist/cli/mcp/oauth-provider.js +77 -0
  187. package/dist/cli/mcp/oauth-redirect.d.ts +3 -0
  188. package/dist/cli/mcp/oauth-redirect.d.ts.map +1 -0
  189. package/dist/cli/mcp/oauth-redirect.js +4 -0
  190. package/dist/cli/mcp/oauth-server.d.ts +2 -0
  191. package/dist/cli/mcp/oauth-server.d.ts.map +1 -0
  192. package/dist/cli/mcp/oauth-server.js +70 -0
  193. package/dist/cli/mcp/oauth-store.d.ts +10 -0
  194. package/dist/cli/mcp/oauth-store.d.ts.map +1 -0
  195. package/dist/cli/mcp/oauth-store.js +27 -0
  196. package/dist/cli/mcp/oauth-ui.d.ts +2 -0
  197. package/dist/cli/mcp/oauth-ui.d.ts.map +1 -0
  198. package/dist/cli/mcp/oauth-ui.js +12 -0
  199. package/dist/cli/mcp/oauth-utils.d.ts +2 -0
  200. package/dist/cli/mcp/oauth-utils.d.ts.map +1 -0
  201. package/dist/cli/mcp/oauth-utils.js +17 -0
  202. package/dist/cli/utils/api-key-setup.d.ts.map +1 -1
  203. package/dist/cli/utils/api-key-setup.js +13 -90
  204. package/dist/cli/utils/api-key-verification.d.ts.map +1 -1
  205. package/dist/cli/utils/api-key-verification.js +36 -0
  206. package/dist/cli/utils/config-validation.d.ts +3 -1
  207. package/dist/cli/utils/config-validation.d.ts.map +1 -1
  208. package/dist/cli/utils/config-validation.js +42 -19
  209. package/dist/cli/utils/dexto-auth-check.d.ts +53 -0
  210. package/dist/cli/utils/dexto-auth-check.d.ts.map +1 -0
  211. package/dist/cli/utils/dexto-auth-check.js +104 -0
  212. package/dist/cli/utils/dexto-setup.d.ts +8 -0
  213. package/dist/cli/utils/dexto-setup.d.ts.map +1 -0
  214. package/dist/cli/utils/dexto-setup.js +17 -0
  215. package/dist/cli/utils/options.d.ts.map +1 -1
  216. package/dist/cli/utils/options.js +5 -1
  217. package/dist/cli/utils/provider-setup.d.ts +4 -0
  218. package/dist/cli/utils/provider-setup.d.ts.map +1 -1
  219. package/dist/cli/utils/provider-setup.js +20 -0
  220. package/dist/cli/utils/version-check.d.ts +45 -0
  221. package/dist/cli/utils/version-check.d.ts.map +1 -0
  222. package/dist/cli/utils/version-check.js +195 -0
  223. package/dist/config/cli-overrides.d.ts +17 -8
  224. package/dist/config/cli-overrides.d.ts.map +1 -1
  225. package/dist/config/cli-overrides.js +36 -22
  226. package/dist/config/effective-llm.d.ts +123 -0
  227. package/dist/config/effective-llm.d.ts.map +1 -0
  228. package/dist/config/effective-llm.js +171 -0
  229. package/dist/index.js +451 -126
  230. package/dist/webui/assets/index-C9JXwpvo.css +1 -0
  231. package/dist/webui/assets/{index-DVQWNLpT.js → index-Dl3mj53P.js} +217 -217
  232. package/dist/webui/index.html +2 -2
  233. package/package.json +9 -8
  234. package/dist/webui/assets/index-BglIVTSG.css +0 -1
@@ -0,0 +1,70 @@
1
+ import { createServer } from 'node:http';
2
+ import { URL } from 'node:url';
3
+ import { ensurePortAvailable } from './oauth-utils.js';
4
+ function escapeHtml(value) {
5
+ return value
6
+ .replace(/&/g, '&')
7
+ .replace(/</g, '&lt;')
8
+ .replace(/>/g, '&gt;')
9
+ .replace(/"/g, '&quot;')
10
+ .replace(/'/g, '&#039;');
11
+ }
12
+ export async function createMcpCallbackServer(redirectUrl) {
13
+ const parsed = new URL(redirectUrl);
14
+ const port = Number(parsed.port || 8080);
15
+ if (!Number.isFinite(port) || port <= 0) {
16
+ throw new Error(`Invalid redirect port: ${parsed.port}`);
17
+ }
18
+ await ensurePortAvailable(port);
19
+ return new Promise((resolve, reject) => {
20
+ const server = createServer((req, res) => {
21
+ if (!req.url) {
22
+ res.writeHead(400);
23
+ res.end('Bad Request');
24
+ return;
25
+ }
26
+ const requestUrl = new URL(req.url, redirectUrl);
27
+ const code = requestUrl.searchParams.get('code');
28
+ const error = requestUrl.searchParams.get('error');
29
+ const errorDescription = requestUrl.searchParams.get('error_description');
30
+ if (code) {
31
+ res.writeHead(200, { 'Content-Type': 'text/html' });
32
+ res.end(`
33
+ <html>
34
+ <body>
35
+ <h1>Authorization Successful</h1>
36
+ <p>You can close this window and return to your terminal.</p>
37
+ </body>
38
+ </html>
39
+ `);
40
+ resolve(code);
41
+ setTimeout(() => server.close(), 3000);
42
+ return;
43
+ }
44
+ if (error) {
45
+ res.writeHead(400, { 'Content-Type': 'text/html' });
46
+ res.end(`
47
+ <html>
48
+ <body>
49
+ <h1>Authorization Failed</h1>
50
+ <p>Error: ${escapeHtml(error)}</p>
51
+ ${errorDescription ? `<p>${escapeHtml(errorDescription)}</p>` : ''}
52
+ </body>
53
+ </html>
54
+ `);
55
+ reject(new Error(`OAuth authorization failed: ${error}${errorDescription ? ` (${errorDescription})` : ''}`));
56
+ setTimeout(() => server.close(), 3000);
57
+ return;
58
+ }
59
+ res.writeHead(400);
60
+ res.end('Missing authorization code');
61
+ });
62
+ server.on('error', (err) => {
63
+ reject(err);
64
+ server.close();
65
+ });
66
+ server.listen(port, () => {
67
+ console.log(`🔐 Awaiting MCP OAuth callback on ${redirectUrl}`);
68
+ });
69
+ });
70
+ }
@@ -0,0 +1,10 @@
1
+ import type { OAuthTokens, OAuthClientInformationMixed } from '@modelcontextprotocol/sdk/shared/auth.js';
2
+ export type McpAuthStore = {
3
+ tokens?: OAuthTokens | undefined;
4
+ clientInformation?: OAuthClientInformationMixed | undefined;
5
+ codeVerifier?: string | undefined;
6
+ };
7
+ export declare function loadMcpAuthStore(serverId: string): Promise<McpAuthStore>;
8
+ export declare function saveMcpAuthStore(serverId: string, store: McpAuthStore): Promise<void>;
9
+ export declare function getMcpAuthStorePath(serverId: string): string;
10
+ //# sourceMappingURL=oauth-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-store.d.ts","sourceRoot":"","sources":["../../../src/cli/mcp/oauth-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACR,WAAW,EACX,2BAA2B,EAC9B,MAAM,0CAA0C,CAAC;AAElD,MAAM,MAAM,YAAY,GAAG;IACvB,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IACjC,iBAAiB,CAAC,EAAE,2BAA2B,GAAG,SAAS,CAAC;IAC5D,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC,CAAC;AAEF,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAW9E;AAED,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAI3F;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE5D"}
@@ -0,0 +1,27 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { getDextoPath } from '@dexto/core';
4
+ export async function loadMcpAuthStore(serverId) {
5
+ const filePath = getMcpAuthStorePath(serverId);
6
+ try {
7
+ const data = await fs.readFile(filePath, 'utf8');
8
+ return JSON.parse(data);
9
+ }
10
+ catch (error) {
11
+ if (error.code === 'ENOENT') {
12
+ return {};
13
+ }
14
+ throw error;
15
+ }
16
+ }
17
+ export async function saveMcpAuthStore(serverId, store) {
18
+ const filePath = getMcpAuthStorePath(serverId);
19
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
20
+ await fs.writeFile(filePath, JSON.stringify(store, null, 2));
21
+ }
22
+ export function getMcpAuthStorePath(serverId) {
23
+ return getDextoPath('mcp-auth', `${sanitizeServerId(serverId)}.json`);
24
+ }
25
+ function sanitizeServerId(serverId) {
26
+ return serverId.replace(/[^a-zA-Z0-9._-]/g, '_');
27
+ }
@@ -0,0 +1,2 @@
1
+ export declare function openAuthUrl(url: string): Promise<void>;
2
+ //# sourceMappingURL=oauth-ui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-ui.d.ts","sourceRoot":"","sources":["../../../src/cli/mcp/oauth-ui.ts"],"names":[],"mappings":"AAEA,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAU5D"}
@@ -0,0 +1,12 @@
1
+ import chalk from 'chalk';
2
+ export async function openAuthUrl(url) {
3
+ console.log(chalk.cyan('🌐 Opening browser for MCP authentication...'));
4
+ try {
5
+ const { default: open } = await import('open');
6
+ await open(url, { wait: false });
7
+ console.log(chalk.green('✅ Browser opened'));
8
+ }
9
+ catch (_error) {
10
+ console.log(chalk.yellow(`💡 Please open manually: ${url}`));
11
+ }
12
+ }
@@ -0,0 +1,2 @@
1
+ export declare function ensurePortAvailable(port: number): Promise<void>;
2
+ //# sourceMappingURL=oauth-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-utils.d.ts","sourceRoot":"","sources":["../../../src/cli/mcp/oauth-utils.ts"],"names":[],"mappings":"AAEA,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBrE"}
@@ -0,0 +1,17 @@
1
+ import { createServer } from 'node:http';
2
+ export async function ensurePortAvailable(port) {
3
+ await new Promise((resolve, reject) => {
4
+ const server = createServer();
5
+ server.listen(port, () => {
6
+ server.close(() => resolve());
7
+ });
8
+ server.on('error', (err) => {
9
+ if (err.code === 'EADDRINUSE') {
10
+ reject(new Error(`Port ${port} is already in use. Please close the application using it and try again.`));
11
+ }
12
+ else {
13
+ reject(err);
14
+ }
15
+ });
16
+ });
17
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"api-key-setup.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/api-key-setup.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAe/C,MAAM,WAAW,iBAAiB;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CACxC,QAAQ,EAAE,WAAW,EACrB,OAAO,GAAE;IACL,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;CACb,GACP,OAAO,CAAC,iBAAiB,CAAC,CAuK5B;AAsMD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAGlE;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACrC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CACxC,QAAQ,EAAE,WAAW,EACrB,KAAK,EAAE,MAAM,GACd,OAAO,CAAC,wBAAwB,CAAC,CAkEnC;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACpC,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,QAAQ,CAAC;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;GASG;AACH,wBAAsB,2BAA2B,CAC7C,aAAa,EAAE,WAAW,EAC1B,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,WAAW,EACzB,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,uBAAuB,CAAC,CAiGlC"}
1
+ {"version":3,"file":"api-key-setup.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/api-key-setup.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAc/C,MAAM,WAAW,iBAAiB;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CACxC,QAAQ,EAAE,WAAW,EACrB,OAAO,GAAE;IACL,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;CACb,GACP,OAAO,CAAC,iBAAiB,CAAC,CAmK5B;AA8GD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAGlE;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACrC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CACxC,QAAQ,EAAE,WAAW,EACrB,KAAK,EAAE,MAAM,GACd,OAAO,CAAC,wBAAwB,CAAC,CAkEnC;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACpC,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,QAAQ,CAAC;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;GASG;AACH,wBAAsB,2BAA2B,CAC7C,aAAa,EAAE,WAAW,EAC1B,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,WAAW,EACzB,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,uBAAuB,CAAC,CAiGlC"}
@@ -4,7 +4,7 @@ import chalk from 'chalk';
4
4
  import { logger, getExecutionContext } from '@dexto/core';
5
5
  import { saveProviderApiKey } from '@dexto/agent-management';
6
6
  import { applyLayeredEnvironmentLoading } from '../../utils/env.js';
7
- import { getProviderDisplayName, validateApiKeyFormat, getProviderInstructions, openApiKeyUrl, getProviderInfo, getProviderEnvVar, PROVIDER_REGISTRY, } from './provider-setup.js';
7
+ import { getProviderDisplayName, validateApiKeyFormat, getProviderInstructions, openApiKeyUrl, getProviderInfo, getProviderEnvVar, } from './provider-setup.js';
8
8
  import { verifyApiKey } from './api-key-verification.js';
9
9
  /**
10
10
  * Interactively prompts the user to set up an API key for a specific provider.
@@ -32,25 +32,20 @@ export async function interactiveApiKeySetup(provider, options = {}) {
32
32
  ? [
33
33
  {
34
34
  value: 'open-browser',
35
- label: 'Open browser & set up now',
36
- hint: 'Opens the API key page in your browser (recommended)',
35
+ label: `${chalk.green('→')} Get API key (opens browser)`,
36
+ hint: "We'll wait while you grab one",
37
37
  },
38
38
  ]
39
39
  : []),
40
40
  {
41
41
  value: 'setup',
42
- label: hasApiKeyUrl ? 'I already have a key' : 'Enter API key now',
43
- hint: 'Paste an existing API key',
42
+ label: `${chalk.cyan('')} Paste existing key`,
43
+ hint: 'I already have an API key',
44
44
  },
45
45
  {
46
46
  value: 'skip',
47
- label: 'Skip for now',
48
- hint: 'Continue without API key - configure later in settings',
49
- },
50
- {
51
- value: 'manual',
52
- label: 'View manual instructions',
53
- hint: 'See how to set up manually',
47
+ label: `${chalk.gray('○')} Set up later`,
48
+ hint: 'Continue without key for now',
54
49
  },
55
50
  ];
56
51
  const action = await p.select({
@@ -64,13 +59,12 @@ export async function interactiveApiKeySetup(provider, options = {}) {
64
59
  return { success: false, cancelled: true };
65
60
  }
66
61
  if (action === 'skip') {
67
- p.log.warn('Skipping API key setup. You can configure it later with: dexto setup');
68
- return { success: true, skipped: true };
69
- }
70
- if (action === 'manual') {
71
- showManualSetupInstructions(provider);
72
- // Don't exit - let them continue
73
- p.log.info('You can configure your API key later with: dexto setup');
62
+ const envVar = getProviderEnvVar(provider);
63
+ p.note(`You can configure your API key later:\n\n` +
64
+ `${chalk.cyan('Option 1:')} Run ${chalk.bold('dexto setup')}\n\n` +
65
+ `${chalk.cyan('Option 2:')} Set environment variable manually:\n` +
66
+ ` ${chalk.dim(`export ${envVar}=your-key-here`)}\n` +
67
+ ` ${chalk.dim('Add to ~/.bashrc or ~/.zshrc to persist')}`, 'Setup Later');
74
68
  return { success: true, skipped: true };
75
69
  }
76
70
  // Open browser if requested
@@ -252,77 +246,6 @@ function showManualSaveInstructions(provider, apiKey) {
252
246
  ];
253
247
  p.note(instructions.join('\n'), chalk.rgb(255, 165, 0)('Manual Setup Required'));
254
248
  }
255
- /**
256
- * Shows manual setup instructions to the user
257
- */
258
- function showManualSetupInstructions(provider) {
259
- const envVar = getProviderEnvVar(provider);
260
- const providerInfo = getProviderInfo(provider);
261
- const envInstructions = getExecutionContext() === 'global-cli'
262
- ? [
263
- `${chalk.bold('2. Save your API key:')}`,
264
- ` ${chalk.gray('Option A:')} Run ${chalk.cyan('dexto setup')} (interactive)`,
265
- ` ${chalk.gray('Option B:')} Create ${chalk.cyan('~/.dexto/.env')} with:`,
266
- ` ${chalk.rgb(255, 165, 0)(`${envVar}=your_api_key_here`)}`,
267
- ]
268
- : [
269
- `${chalk.bold('2. Save your API key:')}`,
270
- ` Create ${chalk.cyan('.env')} in your project with:`,
271
- ` ${chalk.rgb(255, 165, 0)(`${envVar}=your_api_key_here`)}`,
272
- ];
273
- // Build provider URLs list dynamically from registry
274
- const providerUrls = [];
275
- // Add current provider first if it has an API key URL
276
- if (providerInfo?.apiKeyUrl) {
277
- providerUrls.push(` ${chalk.cyan('→')} ${chalk.cyan(getProviderDisplayName(provider))}: ${providerInfo.apiKeyUrl}`);
278
- providerUrls.push(''); // Add spacing
279
- }
280
- // Add recommended/popular providers with API keys
281
- const popularProviders = [
282
- { provider: 'google', color: chalk.green }, // Free
283
- { provider: 'groq', color: chalk.green }, // Free
284
- { provider: 'openai', color: chalk.blue },
285
- { provider: 'anthropic', color: chalk.blue },
286
- { provider: 'xai', color: chalk.blue },
287
- { provider: 'cohere', color: chalk.blue },
288
- ];
289
- for (const { provider: p, color } of popularProviders) {
290
- const info = PROVIDER_REGISTRY[p];
291
- if (info?.apiKeyUrl && p !== provider) {
292
- // Don't duplicate current provider
293
- const freeTag = info.free ? ' (Free)' : '';
294
- providerUrls.push(` ${color('●')} ${color(info.label + freeTag)}: ${info.apiKeyUrl}`);
295
- }
296
- }
297
- // Add gateway providers
298
- const gatewayProviders = ['openrouter', 'glama'];
299
- for (const p of gatewayProviders) {
300
- const info = PROVIDER_REGISTRY[p];
301
- if (info?.apiKeyUrl && p !== provider) {
302
- providerUrls.push(` ${chalk.rgb(255, 165, 0)('●')} ${chalk.rgb(255, 165, 0)(info.label)} (Gateway): ${info.apiKeyUrl}`);
303
- }
304
- }
305
- // Add enterprise providers
306
- const enterpriseProviders = ['vertex', 'bedrock'];
307
- for (const p of enterpriseProviders) {
308
- const info = PROVIDER_REGISTRY[p];
309
- if (info?.apiKeyUrl && p !== provider) {
310
- providerUrls.push(` ${chalk.cyan('●')} ${chalk.cyan(info.label)} (Enterprise): ${info.apiKeyUrl}`);
311
- }
312
- }
313
- const instructions = [
314
- `${chalk.bold('1. Get an API key from your provider:')}`,
315
- ...providerUrls,
316
- ``,
317
- ...envInstructions,
318
- ``,
319
- `${chalk.bold('3. Run dexto again:')}`,
320
- ` ${chalk.cyan('dexto')} or ${chalk.cyan('npx dexto')}`,
321
- ``,
322
- `${chalk.gray('💡 Tip: Start with Google Gemini or Groq for a free experience!')}`,
323
- ].join('\n');
324
- p.note(instructions, chalk.bold('Manual Setup Instructions'));
325
- }
326
249
  /**
327
250
  * Quick check if an API key is already configured for a provider
328
251
  */
@@ -1 +1 @@
1
- {"version":3,"file":"api-key-verification.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/api-key-verification.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/C,MAAM,WAAW,kBAAkB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAC9B,QAAQ,EAAE,WAAW,EACrB,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,kBAAkB,CAAC,CAsC7B"}
1
+ {"version":3,"file":"api-key-verification.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/api-key-verification.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/C,MAAM,WAAW,kBAAkB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAC9B,QAAQ,EAAE,WAAW,EACrB,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,kBAAkB,CAAC,CA0C7B"}
@@ -28,6 +28,10 @@ export async function verifyApiKey(provider, apiKey, _model) {
28
28
  return await verifyOpenRouter(apiKey);
29
29
  case 'glama':
30
30
  return await verifyGlama(apiKey);
31
+ case 'minimax':
32
+ return await verifyMiniMax(apiKey);
33
+ case 'glm':
34
+ return await verifyGLM(apiKey);
31
35
  case 'openai-compatible':
32
36
  case 'litellm':
33
37
  // For custom endpoints, we can't verify without a baseURL
@@ -184,6 +188,38 @@ async function verifyGlama(apiKey) {
184
188
  const error = await parseErrorResponse(response);
185
189
  return { success: false, error };
186
190
  }
191
+ /**
192
+ * Verify MiniMax API key using the OpenAI-compatible models endpoint
193
+ */
194
+ async function verifyMiniMax(apiKey) {
195
+ const response = await fetch('https://api.minimax.chat/v1/models', {
196
+ method: 'GET',
197
+ headers: {
198
+ Authorization: `Bearer ${apiKey}`,
199
+ },
200
+ });
201
+ if (response.ok) {
202
+ return { success: true, modelUsed: 'models-list' };
203
+ }
204
+ const error = await parseErrorResponse(response);
205
+ return { success: false, error };
206
+ }
207
+ /**
208
+ * Verify GLM (Zhipu) API key using the OpenAI-compatible models endpoint
209
+ */
210
+ async function verifyGLM(apiKey) {
211
+ const response = await fetch('https://open.bigmodel.cn/api/paas/v4/models', {
212
+ method: 'GET',
213
+ headers: {
214
+ Authorization: `Bearer ${apiKey}`,
215
+ },
216
+ });
217
+ if (response.ok) {
218
+ return { success: true, modelUsed: 'models-list' };
219
+ }
220
+ const error = await parseErrorResponse(response);
221
+ return { success: false, error };
222
+ }
187
223
  /**
188
224
  * Parse error response from provider API
189
225
  */
@@ -19,7 +19,9 @@ export interface ValidationResult {
19
19
  * @param validationOptions.strict - When true (default), enforces API key requirements.
20
20
  * When false, allows missing credentials for interactive config.
21
21
  */
22
- export declare function validateAgentConfig(config: AgentConfig, interactive?: boolean, validationOptions?: LLMValidationOptions): Promise<ValidationResult>;
22
+ export declare function validateAgentConfig(config: AgentConfig, interactive?: boolean, validationOptions?: LLMValidationOptions & {
23
+ agentPath?: string;
24
+ }): Promise<ValidationResult>;
23
25
  /**
24
26
  * Legacy function for backwards compatibility
25
27
  * @deprecated Use validateAgentConfig with result handling instead
@@ -1 +1 @@
1
- {"version":3,"file":"config-validation.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/config-validation.ts"],"names":[],"mappings":"AAGA,OAAO,EAGH,KAAK,WAAW,EAChB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EAC5B,MAAM,aAAa,CAAC;AAWrB,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,mBAAmB,CACrC,MAAM,EAAE,WAAW,EACnB,WAAW,GAAE,OAAe,EAC5B,iBAAiB,CAAC,EAAE,oBAAoB,GACzC,OAAO,CAAC,gBAAgB,CAAC,CAyC3B;AAwZD;;;GAGG;AACH,wBAAsB,yBAAyB,CAC3C,MAAM,EAAE,WAAW,EACnB,WAAW,GAAE,OAAe,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CAgC/B"}
1
+ {"version":3,"file":"config-validation.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/config-validation.ts"],"names":[],"mappings":"AAGA,OAAO,EAGH,KAAK,WAAW,EAChB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EAC5B,MAAM,aAAa,CAAC;AAYrB,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,mBAAmB,CACrC,MAAM,EAAE,WAAW,EACnB,WAAW,GAAE,OAAe,EAC5B,iBAAiB,CAAC,EAAE,oBAAoB,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAClE,OAAO,CAAC,gBAAgB,CAAC,CAyC3B;AAkbD;;;GAGG;AACH,wBAAsB,yBAAyB,CAC3C,MAAM,EAAE,WAAW,EACnB,WAAW,GAAE,OAAe,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CAgC/B"}
@@ -5,6 +5,7 @@ import { interactiveApiKeySetup } from './api-key-setup.js';
5
5
  import { LLMErrorCode } from '@dexto/core';
6
6
  import { logger } from '@dexto/core';
7
7
  import { getGlobalPreferencesPath, loadGlobalPreferences, saveGlobalPreferences, } from '@dexto/agent-management';
8
+ import { handleSyncAgentsCommand } from '../commands/sync-agents.js';
8
9
  /**
9
10
  * Validates agent config with optional interactive fixes for user experience.
10
11
  * Uses schema parsing to detect API key issues and provides targeted setup.
@@ -51,7 +52,7 @@ export async function validateAgentConfig(config, interactive = false, validatio
51
52
  return await handleBaseURLError(baseURLError.provider, config, errors, validationOptions);
52
53
  }
53
54
  // Other validation errors - show options
54
- return await handleOtherErrors(errors);
55
+ return await handleOtherErrors(errors, validationOptions);
55
56
  }
56
57
  /**
57
58
  * Handle API key validation errors interactively
@@ -92,7 +93,7 @@ async function handleApiKeyError(provider, config, errors, validationOptions) {
92
93
  return { success: false, errors, skipped: true };
93
94
  }
94
95
  if (action === 'edit') {
95
- showManualEditInstructions();
96
+ showManualEditInstructions(undefined);
96
97
  return { success: false, errors, skipped: true };
97
98
  }
98
99
  // 'skip' - continue anyway
@@ -154,7 +155,7 @@ async function handleBaseURLError(provider, config, errors, validationOptions) {
154
155
  return { success: false, errors, skipped: true };
155
156
  }
156
157
  if (action === 'edit') {
157
- showManualEditInstructions();
158
+ showManualEditInstructions(undefined);
158
159
  return { success: false, errors, skipped: true };
159
160
  }
160
161
  // 'skip' - continue anyway
@@ -228,7 +229,7 @@ async function interactiveBaseURLSetup(provider, existingBaseURL) {
228
229
  /**
229
230
  * Handle non-API-key validation errors interactively
230
231
  */
231
- async function handleOtherErrors(errors) {
232
+ async function handleOtherErrors(errors, validationOptions) {
232
233
  console.log(chalk.rgb(255, 165, 0)('\n⚠️ Configuration issues detected:\n'));
233
234
  for (const error of errors) {
234
235
  console.log(chalk.red(` • ${error}`));
@@ -237,6 +238,11 @@ async function handleOtherErrors(errors) {
237
238
  const action = await p.select({
238
239
  message: 'How would you like to proceed?',
239
240
  options: [
241
+ {
242
+ value: 'sync',
243
+ label: 'Sync agent config',
244
+ hint: 'Update from bundled registry (recommended)',
245
+ },
240
246
  {
241
247
  value: 'skip',
242
248
  label: 'Continue anyway',
@@ -247,23 +253,27 @@ async function handleOtherErrors(errors) {
247
253
  label: 'Edit configuration manually',
248
254
  hint: 'Show file path and instructions',
249
255
  },
250
- {
251
- value: 'setup',
252
- label: 'Run setup again',
253
- hint: 'Reconfigure from scratch',
254
- },
255
256
  ],
256
257
  });
257
258
  if (p.isCancel(action)) {
258
259
  showNextSteps();
259
260
  return { success: false, errors, skipped: true };
260
261
  }
261
- if (action === 'edit') {
262
- showManualEditInstructions();
263
- return { success: false, errors, skipped: true };
262
+ if (action === 'sync') {
263
+ try {
264
+ // Run sync-agents to update the agent config
265
+ await handleSyncAgentsCommand({ force: true, quiet: false });
266
+ // Exit after sync - user needs to restart dexto
267
+ p.outro(chalk.gray('Run dexto to start Dexto'));
268
+ process.exit(0);
269
+ }
270
+ catch (error) {
271
+ p.log.error(`Failed to sync agent: ${error instanceof Error ? error.message : String(error)}`);
272
+ return { success: false, errors, skipped: true };
273
+ }
264
274
  }
265
- if (action === 'setup') {
266
- p.log.info('Run: dexto setup --force');
275
+ if (action === 'edit') {
276
+ showManualEditInstructions(validationOptions?.agentPath);
267
277
  return { success: false, errors, skipped: true };
268
278
  }
269
279
  // 'skip' - continue anyway
@@ -293,19 +303,32 @@ function showNextSteps() {
293
303
  /**
294
304
  * Show manual edit instructions
295
305
  */
296
- function showManualEditInstructions() {
306
+ function showManualEditInstructions(agentPath) {
297
307
  const prefsPath = getGlobalPreferencesPath();
308
+ const configPaths = [` ${chalk.cyan('Global preferences:')} ${prefsPath}`];
309
+ if (agentPath) {
310
+ configPaths.push(` ${chalk.cyan('Agent config:')} ${agentPath}`);
311
+ }
312
+ else {
313
+ configPaths.push(` ${chalk.cyan('Agent configs:')} ~/.dexto/agents/*/`);
314
+ }
298
315
  p.note([
299
316
  `Your configuration files:`,
300
317
  ``,
301
- ` ${chalk.cyan('Global preferences:')} ${prefsPath}`,
302
- ` ${chalk.cyan('Agent configs:')} ~/.dexto/agents/*/`,
318
+ ...configPaths,
303
319
  ``,
304
320
  `Edit the appropriate file and run dexto again.`,
305
321
  ``,
306
322
  chalk.gray('Example commands:'),
307
- chalk.gray(` code ${prefsPath} # Open in VS Code`),
308
- chalk.gray(` nano ${prefsPath} # Edit in terminal`),
323
+ ...(agentPath
324
+ ? [
325
+ chalk.gray(` code ${agentPath} # Open in VS Code`),
326
+ chalk.gray(` nano ${agentPath} # Edit in terminal`),
327
+ ]
328
+ : [
329
+ chalk.gray(` code ${prefsPath} # Open in VS Code`),
330
+ chalk.gray(` nano ${prefsPath} # Edit in terminal`),
331
+ ]),
309
332
  ].join('\n'), 'Manual Configuration');
310
333
  }
311
334
  /**
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Dexto Authentication Check
3
+ *
4
+ * Validates that users configured to use Dexto credits are properly authenticated.
5
+ * This prevents the confusing state where user is logged out but still has
6
+ * Dexto credits configured (which would fail at runtime).
7
+ *
8
+ * ## When This Check Runs
9
+ *
10
+ * - On CLI startup, after loading preferences
11
+ * - Before attempting to use the LLM
12
+ *
13
+ * ## Why This Exists
14
+ *
15
+ * When a user runs `dexto logout` while configured with `provider: dexto`,
16
+ * their preferences.yml still points to Dexto. Without this check, the CLI
17
+ * would attempt to use Dexto credits and fail with "Invalid API key" errors.
18
+ *
19
+ * Instead, we catch this state early and offer clear options:
20
+ * - Log back in to continue using Dexto credits
21
+ * - Run setup to configure a different provider (BYOK)
22
+ *
23
+ * @module dexto-auth-check
24
+ */
25
+ export interface DextoAuthCheckResult {
26
+ shouldContinue: boolean;
27
+ action?: 'login' | 'setup' | 'cancel';
28
+ }
29
+ /**
30
+ * Check if user is configured to use Dexto credits but is not authenticated.
31
+ * This can happen if user logged out after setting up with Dexto credits.
32
+ *
33
+ * Uses getEffectiveLLMConfig() to determine the actual LLM that will be used,
34
+ * considering all config layers (local, preferences, bundled).
35
+ *
36
+ * @param interactive Whether to show interactive prompts
37
+ * @param agentId Agent to check config for (default: 'coding-agent')
38
+ * @returns Whether to continue startup and what action was taken
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * const result = await checkDextoAuthState(true, 'coding-agent');
43
+ * if (!result.shouldContinue) {
44
+ * if (result.action === 'login') {
45
+ * await handleLoginCommand();
46
+ * } else if (result.action === 'setup') {
47
+ * await handleSetupCommand();
48
+ * }
49
+ * }
50
+ * ```
51
+ */
52
+ export declare function checkDextoAuthState(interactive?: boolean, agentId?: string): Promise<DextoAuthCheckResult>;
53
+ //# sourceMappingURL=dexto-auth-check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dexto-auth-check.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/dexto-auth-check.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAOH,MAAM,WAAW,oBAAoB;IACjC,cAAc,EAAE,OAAO,CAAC;IACxB,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAC;CACzC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,mBAAmB,CACrC,WAAW,GAAE,OAAc,EAC3B,OAAO,GAAE,MAAuB,GACjC,OAAO,CAAC,oBAAoB,CAAC,CA8D/B"}