dexto 1.4.0 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -7
- package/dist/agents/agent-template.yml +2 -2
- package/dist/agents/coding-agent/coding-agent.yml +22 -16
- package/dist/agents/database-agent/database-agent.yml +2 -2
- package/dist/agents/default-agent.yml +7 -5
- package/dist/agents/github-agent/github-agent.yml +2 -2
- package/dist/agents/product-name-researcher/product-name-researcher.yml +2 -2
- package/dist/agents/talk2pdf-agent/talk2pdf-agent.yml +2 -2
- package/dist/analytics/events.d.ts +13 -6
- package/dist/analytics/events.d.ts.map +1 -1
- package/dist/analytics/index.d.ts +1 -1
- package/dist/analytics/index.d.ts.map +1 -1
- package/dist/analytics/index.js +6 -2
- package/dist/api/server-hono.d.ts.map +1 -1
- package/dist/api/server-hono.js +27 -5
- package/dist/cli/cli-subscriber.d.ts +4 -0
- package/dist/cli/cli-subscriber.d.ts.map +1 -1
- package/dist/cli/cli-subscriber.js +40 -2
- package/dist/cli/commands/create-app.d.ts +16 -14
- package/dist/cli/commands/create-app.d.ts.map +1 -1
- package/dist/cli/commands/create-app.js +626 -102
- package/dist/cli/commands/create-image.d.ts +7 -0
- package/dist/cli/commands/create-image.d.ts.map +1 -0
- package/dist/cli/commands/create-image.js +201 -0
- package/dist/cli/commands/helpers/formatters.js +7 -7
- package/dist/cli/commands/index.d.ts +2 -1
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +2 -1
- package/dist/cli/commands/init-app.js +7 -7
- package/dist/cli/commands/install.d.ts +0 -3
- package/dist/cli/commands/install.d.ts.map +1 -1
- package/dist/cli/commands/install.js +10 -35
- package/dist/cli/commands/interactive-commands/command-parser.d.ts +1 -1
- package/dist/cli/commands/interactive-commands/command-parser.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/command-parser.js +18 -8
- package/dist/cli/commands/interactive-commands/general-commands.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/general-commands.js +64 -1
- package/dist/cli/commands/interactive-commands/prompt-commands.js +11 -11
- package/dist/cli/commands/interactive-commands/system/system-commands.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/system/system-commands.js +6 -5
- package/dist/cli/commands/list-agents.js +2 -2
- package/dist/cli/commands/session-commands.js +16 -16
- package/dist/cli/commands/setup.d.ts +13 -5
- package/dist/cli/commands/setup.d.ts.map +1 -1
- package/dist/cli/commands/setup.js +995 -65
- package/dist/cli/commands/which.js +1 -1
- package/dist/cli/ink-cli/components/ApprovalPrompt.d.ts +2 -0
- package/dist/cli/ink-cli/components/ApprovalPrompt.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/ApprovalPrompt.js +29 -7
- package/dist/cli/ink-cli/components/CustomInput.js +1 -1
- package/dist/cli/ink-cli/components/EditableMultiLineInput.js +4 -4
- package/dist/cli/ink-cli/components/ElicitationForm.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/ElicitationForm.js +6 -6
- package/dist/cli/ink-cli/components/ErrorBoundary.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/ErrorBoundary.js +1 -1
- package/dist/cli/ink-cli/components/Footer.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/Footer.js +1 -1
- package/dist/cli/ink-cli/components/HistorySearchBar.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/HistorySearchBar.js +1 -1
- package/dist/cli/ink-cli/components/MultiLineInput.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/MultiLineInput.js +3 -3
- package/dist/cli/ink-cli/components/ResourceAutocomplete.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/ResourceAutocomplete.js +4 -4
- package/dist/cli/ink-cli/components/SlashCommandAutocomplete.js +3 -3
- package/dist/cli/ink-cli/components/StatusBar.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/StatusBar.js +7 -5
- package/dist/cli/ink-cli/components/TextBufferInput.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/TextBufferInput.js +13 -9
- package/dist/cli/ink-cli/components/base/BaseAutocomplete.js +4 -4
- package/dist/cli/ink-cli/components/base/BaseSelector.js +2 -2
- package/dist/cli/ink-cli/components/chat/Footer.js +1 -1
- package/dist/cli/ink-cli/components/chat/Header.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/chat/Header.js +2 -4
- package/dist/cli/ink-cli/components/chat/MessageItem.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/chat/MessageItem.js +9 -6
- package/dist/cli/ink-cli/components/chat/MessageList.js +1 -1
- package/dist/cli/ink-cli/components/chat/QueuedMessagesDisplay.js +1 -1
- package/dist/cli/ink-cli/components/chat/ToolIcon.d.ts +1 -1
- package/dist/cli/ink-cli/components/chat/ToolIcon.js +4 -4
- package/dist/cli/ink-cli/components/chat/styled-boxes/ConfigBox.js +1 -1
- package/dist/cli/ink-cli/components/chat/styled-boxes/HelpBox.js +1 -1
- package/dist/cli/ink-cli/components/chat/styled-boxes/LogConfigBox.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/chat/styled-boxes/LogConfigBox.js +2 -2
- package/dist/cli/ink-cli/components/chat/styled-boxes/SessionHistoryBox.js +5 -5
- package/dist/cli/ink-cli/components/chat/styled-boxes/SessionListBox.js +2 -2
- package/dist/cli/ink-cli/components/chat/styled-boxes/ShortcutsBox.js +1 -1
- package/dist/cli/ink-cli/components/chat/styled-boxes/StatsBox.js +1 -1
- package/dist/cli/ink-cli/components/chat/styled-boxes/StyledBox.js +2 -2
- package/dist/cli/ink-cli/components/modes/AlternateBufferCLI.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/modes/AlternateBufferCLI.js +1 -1
- package/dist/cli/ink-cli/components/modes/StaticCLI.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/modes/StaticCLI.js +1 -1
- package/dist/cli/ink-cli/components/overlays/ApiKeyInput.js +1 -1
- package/dist/cli/ink-cli/components/overlays/CustomModelWizard.d.ts +10 -2
- package/dist/cli/ink-cli/components/overlays/CustomModelWizard.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/CustomModelWizard.js +209 -89
- package/dist/cli/ink-cli/components/overlays/LogLevelSelector.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/LogLevelSelector.js +2 -2
- package/dist/cli/ink-cli/components/overlays/McpAddChoice.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/McpAddChoice.js +1 -1
- package/dist/cli/ink-cli/components/overlays/McpAddSelector.js +1 -1
- package/dist/cli/ink-cli/components/overlays/McpCustomTypeSelector.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/McpCustomTypeSelector.js +2 -2
- package/dist/cli/ink-cli/components/overlays/McpCustomWizard.js +1 -1
- package/dist/cli/ink-cli/components/overlays/McpRemoveSelector.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/McpRemoveSelector.js +1 -1
- package/dist/cli/ink-cli/components/overlays/McpSelector.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/McpSelector.js +1 -1
- package/dist/cli/ink-cli/components/overlays/McpServerActions.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/McpServerActions.js +2 -2
- package/dist/cli/ink-cli/components/overlays/McpServerList.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/McpServerList.js +1 -1
- package/dist/cli/ink-cli/components/overlays/ModelSelectorRefactored.d.ts +6 -5
- package/dist/cli/ink-cli/components/overlays/ModelSelectorRefactored.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/ModelSelectorRefactored.js +284 -68
- package/dist/cli/ink-cli/components/overlays/PromptAddChoice.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/PromptAddChoice.js +2 -2
- package/dist/cli/ink-cli/components/overlays/PromptAddWizard.js +1 -1
- package/dist/cli/ink-cli/components/overlays/PromptDeleteSelector.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/PromptDeleteSelector.js +2 -2
- package/dist/cli/ink-cli/components/overlays/PromptList.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/PromptList.js +2 -2
- package/dist/cli/ink-cli/components/overlays/SearchOverlay.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/SearchOverlay.js +4 -4
- package/dist/cli/ink-cli/components/overlays/SessionSubcommandSelector.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/SessionSubcommandSelector.js +1 -1
- package/dist/cli/ink-cli/components/overlays/StreamSelector.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/StreamSelector.js +1 -1
- package/dist/cli/ink-cli/components/overlays/ToolBrowser.js +12 -12
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/LocalModelWizard.d.ts +25 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/LocalModelWizard.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/LocalModelWizard.js +609 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/index.d.ts +15 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/index.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/index.js +14 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.d.ts +33 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.js +462 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/ApiKeyStep.d.ts +25 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/ApiKeyStep.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/ApiKeyStep.js +29 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/ProviderSelector.d.ts +17 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/ProviderSelector.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/ProviderSelector.js +11 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/SetupInfoBanner.d.ts +20 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/SetupInfoBanner.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/SetupInfoBanner.js +10 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/WizardStepInput.d.ts +30 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/WizardStepInput.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/WizardStepInput.js +13 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/index.d.ts +8 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/index.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/shared/index.js +7 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/types.d.ts +85 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/types.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/types.js +38 -0
- package/dist/cli/ink-cli/components/renderers/DiffRenderer.js +2 -2
- package/dist/cli/ink-cli/components/renderers/FilePreviewRenderer.js +1 -1
- package/dist/cli/ink-cli/components/renderers/FileRenderer.js +4 -4
- package/dist/cli/ink-cli/components/renderers/GenericRenderer.js +2 -2
- package/dist/cli/ink-cli/components/renderers/SearchRenderer.js +1 -1
- package/dist/cli/ink-cli/components/renderers/ShellRenderer.js +3 -3
- package/dist/cli/ink-cli/components/renderers/diff-shared.js +1 -1
- package/dist/cli/ink-cli/components/shared/MarkdownText.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/shared/MarkdownText.js +8 -6
- package/dist/cli/ink-cli/containers/InputContainer.d.ts.map +1 -1
- package/dist/cli/ink-cli/containers/InputContainer.js +23 -1
- package/dist/cli/ink-cli/containers/OverlayContainer.d.ts.map +1 -1
- package/dist/cli/ink-cli/containers/OverlayContainer.js +81 -25
- package/dist/cli/ink-cli/hooks/useAgentEvents.d.ts +9 -2
- package/dist/cli/ink-cli/hooks/useAgentEvents.d.ts.map +1 -1
- package/dist/cli/ink-cli/hooks/useAgentEvents.js +148 -6
- package/dist/cli/ink-cli/hooks/useCLIState.d.ts +1 -1
- package/dist/cli/ink-cli/hooks/useCLIState.d.ts.map +1 -1
- package/dist/cli/ink-cli/hooks/useCLIState.js +7 -2
- package/dist/cli/ink-cli/hooks/useTokenCounter.d.ts +11 -7
- package/dist/cli/ink-cli/hooks/useTokenCounter.d.ts.map +1 -1
- package/dist/cli/ink-cli/hooks/useTokenCounter.js +41 -18
- package/dist/cli/ink-cli/services/processStream.d.ts.map +1 -1
- package/dist/cli/ink-cli/services/processStream.js +97 -17
- package/dist/cli/ink-cli/state/types.d.ts +5 -4
- package/dist/cli/ink-cli/state/types.d.ts.map +1 -1
- package/dist/cli/ink-cli/utils/messageFormatting.d.ts +5 -0
- package/dist/cli/ink-cli/utils/messageFormatting.d.ts.map +1 -1
- package/dist/cli/ink-cli/utils/messageFormatting.js +59 -1
- package/dist/cli/ink-cli/utils/toolUtils.d.ts.map +1 -1
- package/dist/cli/ink-cli/utils/toolUtils.js +2 -0
- package/dist/cli/utils/api-key-setup.d.ts +54 -4
- package/dist/cli/utils/api-key-setup.d.ts.map +1 -1
- package/dist/cli/utils/api-key-setup.js +433 -107
- package/dist/cli/utils/api-key-verification.d.ts +17 -0
- package/dist/cli/utils/api-key-verification.d.ts.map +1 -0
- package/dist/cli/utils/api-key-verification.js +211 -0
- package/dist/cli/utils/config-validation.d.ts +22 -2
- package/dist/cli/utils/config-validation.d.ts.map +1 -1
- package/dist/cli/utils/config-validation.js +354 -25
- package/dist/cli/utils/local-model-setup.d.ts +46 -0
- package/dist/cli/utils/local-model-setup.d.ts.map +1 -0
- package/dist/cli/utils/local-model-setup.js +662 -0
- package/dist/cli/utils/options.js +1 -1
- package/dist/cli/utils/prompt-helpers.d.ts +47 -0
- package/dist/cli/utils/prompt-helpers.d.ts.map +1 -0
- package/dist/cli/utils/prompt-helpers.js +66 -0
- package/dist/cli/utils/provider-setup.d.ts +66 -8
- package/dist/cli/utils/provider-setup.d.ts.map +1 -1
- package/dist/cli/utils/provider-setup.js +324 -84
- package/dist/cli/utils/scaffolding-utils.d.ts +76 -0
- package/dist/cli/utils/scaffolding-utils.d.ts.map +1 -0
- package/dist/cli/utils/scaffolding-utils.js +246 -0
- package/dist/cli/utils/setup-utils.d.ts +16 -0
- package/dist/cli/utils/setup-utils.d.ts.map +1 -1
- package/dist/cli/utils/setup-utils.js +72 -21
- package/dist/cli/utils/template-engine.d.ts +65 -0
- package/dist/cli/utils/template-engine.d.ts.map +1 -0
- package/dist/cli/utils/template-engine.js +1089 -0
- package/dist/config/cli-overrides.d.ts +44 -1
- package/dist/config/cli-overrides.d.ts.map +1 -1
- package/dist/config/cli-overrides.js +102 -0
- package/dist/index.js +339 -56
- package/dist/webui/assets/index-8j-KMkX1.js +2054 -0
- package/dist/webui/assets/index-c_AX24V4.css +1 -0
- package/dist/webui/index.html +3 -9
- package/dist/webui/logos/aws-color.svg +1 -0
- package/dist/webui/logos/dexto/dexto_logo.svg +1 -1
- package/dist/webui/logos/dexto/dexto_logo_light.svg +6 -6
- package/dist/webui/logos/glama.svg +7 -0
- package/dist/webui/logos/litellm.svg +7 -0
- package/dist/webui/logos/openrouter.svg +1 -0
- package/package.json +8 -7
- package/dist/webui/assets/index-BkwPkZpd.css +0 -1
- package/dist/webui/assets/index-D9u1XfyH.js +0 -2025
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consistent prompt helpers for CLI flows.
|
|
3
|
+
*
|
|
4
|
+
* These helpers wrap @clack/prompts with automatic cancel handling.
|
|
5
|
+
* Use for linear flows where cancel should exit the process.
|
|
6
|
+
*/
|
|
7
|
+
import * as p from '@clack/prompts';
|
|
8
|
+
type SelectOptions = Parameters<typeof p.select>[0];
|
|
9
|
+
type TextOptions = Parameters<typeof p.text>[0];
|
|
10
|
+
type ConfirmOptions = Parameters<typeof p.confirm>[0];
|
|
11
|
+
/**
|
|
12
|
+
* Select prompt that exits on cancel.
|
|
13
|
+
* Use for linear flows where cancel should abort the entire operation.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* const choice = await selectOrExit<'a' | 'b'>({
|
|
17
|
+
* message: 'Pick one',
|
|
18
|
+
* options: [{ value: 'a', label: 'A' }, { value: 'b', label: 'B' }]
|
|
19
|
+
* }, 'Operation cancelled');
|
|
20
|
+
*/
|
|
21
|
+
export declare function selectOrExit<T extends string>(options: SelectOptions, cancelMessage?: string): Promise<T>;
|
|
22
|
+
/**
|
|
23
|
+
* Text prompt that exits on cancel.
|
|
24
|
+
* Use for linear flows where cancel should abort the entire operation.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* const name = await textOrExit({
|
|
28
|
+
* message: 'Enter your name',
|
|
29
|
+
* placeholder: 'John Doe'
|
|
30
|
+
* }, 'Operation cancelled');
|
|
31
|
+
*/
|
|
32
|
+
export declare function textOrExit(options: TextOptions, cancelMessage?: string): Promise<string>;
|
|
33
|
+
/**
|
|
34
|
+
* Confirm prompt that exits on cancel.
|
|
35
|
+
* Use for linear flows where cancel should abort the entire operation.
|
|
36
|
+
*
|
|
37
|
+
* Note: This only exits on cancel (Ctrl+C), not when user selects "No".
|
|
38
|
+
* For "must confirm or abort" behavior, check the return value separately.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* const confirmed = await confirmOrExit({
|
|
42
|
+
* message: 'Are you sure?'
|
|
43
|
+
* }, 'Operation cancelled');
|
|
44
|
+
*/
|
|
45
|
+
export declare function confirmOrExit(options: ConfirmOptions, cancelMessage?: string): Promise<boolean>;
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=prompt-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-helpers.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/prompt-helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AAMpC,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AACpD,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAChD,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AAMtD;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAAC,CAAC,SAAS,MAAM,EAC/C,OAAO,EAAE,aAAa,EACtB,aAAa,SAAc,GAC5B,OAAO,CAAC,CAAC,CAAC,CAOZ;AAED;;;;;;;;;GASG;AACH,wBAAsB,UAAU,CAC5B,OAAO,EAAE,WAAW,EACpB,aAAa,SAAc,GAC5B,OAAO,CAAC,MAAM,CAAC,CAOjB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAC/B,OAAO,EAAE,cAAc,EACvB,aAAa,SAAc,GAC5B,OAAO,CAAC,OAAO,CAAC,CAOlB"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consistent prompt helpers for CLI flows.
|
|
3
|
+
*
|
|
4
|
+
* These helpers wrap @clack/prompts with automatic cancel handling.
|
|
5
|
+
* Use for linear flows where cancel should exit the process.
|
|
6
|
+
*/
|
|
7
|
+
import * as p from '@clack/prompts';
|
|
8
|
+
// =============================================================================
|
|
9
|
+
// LINEAR FLOW HELPERS (cancel = exit)
|
|
10
|
+
// =============================================================================
|
|
11
|
+
/**
|
|
12
|
+
* Select prompt that exits on cancel.
|
|
13
|
+
* Use for linear flows where cancel should abort the entire operation.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* const choice = await selectOrExit<'a' | 'b'>({
|
|
17
|
+
* message: 'Pick one',
|
|
18
|
+
* options: [{ value: 'a', label: 'A' }, { value: 'b', label: 'B' }]
|
|
19
|
+
* }, 'Operation cancelled');
|
|
20
|
+
*/
|
|
21
|
+
export async function selectOrExit(options, cancelMessage = 'Cancelled') {
|
|
22
|
+
const result = await p.select(options);
|
|
23
|
+
if (p.isCancel(result)) {
|
|
24
|
+
p.cancel(cancelMessage);
|
|
25
|
+
process.exit(0);
|
|
26
|
+
}
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Text prompt that exits on cancel.
|
|
31
|
+
* Use for linear flows where cancel should abort the entire operation.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* const name = await textOrExit({
|
|
35
|
+
* message: 'Enter your name',
|
|
36
|
+
* placeholder: 'John Doe'
|
|
37
|
+
* }, 'Operation cancelled');
|
|
38
|
+
*/
|
|
39
|
+
export async function textOrExit(options, cancelMessage = 'Cancelled') {
|
|
40
|
+
const result = await p.text(options);
|
|
41
|
+
if (p.isCancel(result)) {
|
|
42
|
+
p.cancel(cancelMessage);
|
|
43
|
+
process.exit(0);
|
|
44
|
+
}
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Confirm prompt that exits on cancel.
|
|
49
|
+
* Use for linear flows where cancel should abort the entire operation.
|
|
50
|
+
*
|
|
51
|
+
* Note: This only exits on cancel (Ctrl+C), not when user selects "No".
|
|
52
|
+
* For "must confirm or abort" behavior, check the return value separately.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* const confirmed = await confirmOrExit({
|
|
56
|
+
* message: 'Are you sure?'
|
|
57
|
+
* }, 'Operation cancelled');
|
|
58
|
+
*/
|
|
59
|
+
export async function confirmOrExit(options, cancelMessage = 'Cancelled') {
|
|
60
|
+
const result = await p.confirm(options);
|
|
61
|
+
if (p.isCancel(result)) {
|
|
62
|
+
p.cancel(cancelMessage);
|
|
63
|
+
process.exit(0);
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
@@ -1,23 +1,62 @@
|
|
|
1
1
|
import { type LLMProvider } from '@dexto/core';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Provider category for organizing the selection menu
|
|
4
|
+
*/
|
|
5
|
+
type ProviderCategory = 'recommended' | 'local' | 'cloud' | 'gateway' | 'enterprise';
|
|
6
|
+
/**
|
|
7
|
+
* Extended provider information for setup
|
|
8
|
+
*/
|
|
9
|
+
interface ProviderOption {
|
|
10
|
+
value: LLMProvider;
|
|
11
|
+
label: string;
|
|
12
|
+
hint: string;
|
|
13
|
+
category: ProviderCategory;
|
|
14
|
+
apiKeyUrl?: string;
|
|
15
|
+
apiKeyPrefix?: string;
|
|
16
|
+
apiKeyMinLength?: number;
|
|
17
|
+
requiresBaseURL?: boolean;
|
|
18
|
+
envVar: string;
|
|
19
|
+
free?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Provider configuration registry
|
|
23
|
+
* Organized by category for better UX
|
|
24
|
+
*/
|
|
25
|
+
export declare const PROVIDER_REGISTRY: Partial<Record<LLMProvider, ProviderOption>>;
|
|
26
|
+
/**
|
|
27
|
+
* Interactive provider selection with back option.
|
|
28
|
+
* @returns Selected provider, '_back' if back selected, or null if cancelled
|
|
29
|
+
*/
|
|
30
|
+
export declare function selectProvider(): Promise<LLMProvider | '_back' | null>;
|
|
31
|
+
/**
|
|
32
|
+
* Get provider display name
|
|
33
|
+
*/
|
|
34
|
+
export declare function getProviderDisplayName(provider: LLMProvider): string;
|
|
35
|
+
/**
|
|
36
|
+
* Get provider option info
|
|
37
|
+
*/
|
|
38
|
+
export declare function getProviderInfo(provider: LLMProvider): ProviderOption | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* Legacy PROVIDER_OPTIONS for backwards compatibility with init-app
|
|
4
41
|
*/
|
|
5
42
|
export declare const PROVIDER_OPTIONS: {
|
|
6
|
-
value:
|
|
43
|
+
value: LLMProvider;
|
|
7
44
|
label: string;
|
|
8
45
|
hint: string;
|
|
9
46
|
}[];
|
|
10
47
|
/**
|
|
11
|
-
*
|
|
12
|
-
* @returns Selected provider or null if cancelled
|
|
48
|
+
* Get API key format hint for a provider
|
|
13
49
|
*/
|
|
14
|
-
export declare function
|
|
50
|
+
export declare function getApiKeyFormatHint(provider: LLMProvider): string | null;
|
|
15
51
|
/**
|
|
16
|
-
*
|
|
52
|
+
* Validates API key format for a provider with detailed error messages
|
|
17
53
|
*/
|
|
18
|
-
export declare function
|
|
54
|
+
export declare function validateApiKeyFormat(apiKey: string, provider: LLMProvider): {
|
|
55
|
+
valid: boolean;
|
|
56
|
+
error?: string;
|
|
57
|
+
};
|
|
19
58
|
/**
|
|
20
|
-
*
|
|
59
|
+
* Legacy validation function for backwards compatibility
|
|
21
60
|
*/
|
|
22
61
|
export declare function isValidApiKeyFormat(apiKey: string, provider: LLMProvider): boolean;
|
|
23
62
|
/**
|
|
@@ -26,5 +65,24 @@ export declare function isValidApiKeyFormat(apiKey: string, provider: LLMProvide
|
|
|
26
65
|
export declare function getProviderInstructions(provider: LLMProvider): {
|
|
27
66
|
title: string;
|
|
28
67
|
content: string;
|
|
68
|
+
url?: string | undefined;
|
|
29
69
|
} | null;
|
|
70
|
+
/**
|
|
71
|
+
* Open the API key URL in the browser
|
|
72
|
+
*/
|
|
73
|
+
export declare function openApiKeyUrl(provider: LLMProvider): Promise<boolean>;
|
|
74
|
+
/**
|
|
75
|
+
* Check if provider requires a base URL
|
|
76
|
+
*/
|
|
77
|
+
export declare function providerRequiresBaseURL(provider: LLMProvider): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Get default model for provider, with fallback for custom providers
|
|
80
|
+
*/
|
|
81
|
+
export declare function getDefaultModel(provider: LLMProvider): string;
|
|
82
|
+
/**
|
|
83
|
+
* Get environment variable name for provider's API key.
|
|
84
|
+
* Uses the canonical env var from the core api-key-resolver.
|
|
85
|
+
*/
|
|
86
|
+
export declare function getProviderEnvVar(provider: LLMProvider): string;
|
|
87
|
+
export {};
|
|
30
88
|
//# sourceMappingURL=provider-setup.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-setup.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/provider-setup.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"provider-setup.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/provider-setup.ts"],"names":[],"mappings":"AAKA,OAAO,EACH,KAAK,WAAW,EAInB,MAAM,aAAa,CAAC;AAGrB;;GAEG;AACH,KAAK,gBAAgB,GAAG,aAAa,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,YAAY,CAAC;AAErF;;GAEG;AACH,UAAU,cAAc;IACpB,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,CA8H1E,CAAC;AA0FF;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,WAAW,GAAG,OAAO,GAAG,IAAI,CAAC,CAoB5E;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,CAEpE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,WAAW,GAAG,cAAc,GAAG,SAAS,CAEjF;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB;WA1GmB,WAAW;WAAS,MAAM;UAAQ,MAAM;GA0GlC,CAAC;AAEvD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAIxE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAChC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,WAAW,GACtB;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CA0BpC;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,OAAO,CAElF;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACnC,QAAQ,EAAE,WAAW,GACtB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GAAG,IAAI,CAwBrE;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAU3E;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAEtE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,CAY7D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,CAE/D"}
|
|
@@ -1,122 +1,362 @@
|
|
|
1
1
|
// packages/cli/src/cli/utils/provider-setup.ts
|
|
2
2
|
import * as p from '@clack/prompts';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
|
+
import open from 'open';
|
|
5
|
+
import { LLM_PROVIDERS, LLM_REGISTRY, getDefaultModelForProvider, } from '@dexto/core';
|
|
6
|
+
import { getPrimaryApiKeyEnvVar } from '@dexto/agent-management';
|
|
4
7
|
/**
|
|
5
|
-
*
|
|
8
|
+
* Provider configuration registry
|
|
9
|
+
* Organized by category for better UX
|
|
6
10
|
*/
|
|
7
|
-
export const
|
|
8
|
-
{
|
|
11
|
+
export const PROVIDER_REGISTRY = {
|
|
12
|
+
google: {
|
|
9
13
|
value: 'google',
|
|
10
|
-
label: '
|
|
11
|
-
hint: 'Free tier
|
|
14
|
+
label: 'Google Gemini',
|
|
15
|
+
hint: 'Free tier, 1M+ context, multimodal',
|
|
16
|
+
category: 'recommended',
|
|
17
|
+
apiKeyUrl: 'https://aistudio.google.com/apikey',
|
|
18
|
+
apiKeyPrefix: 'AIza',
|
|
19
|
+
apiKeyMinLength: 20,
|
|
20
|
+
envVar: 'GOOGLE_API_KEY',
|
|
21
|
+
free: true,
|
|
12
22
|
},
|
|
13
|
-
{
|
|
23
|
+
groq: {
|
|
14
24
|
value: 'groq',
|
|
15
|
-
label: '
|
|
16
|
-
hint: 'Free tier
|
|
25
|
+
label: 'Groq',
|
|
26
|
+
hint: 'Free tier, ultra-fast inference',
|
|
27
|
+
category: 'recommended',
|
|
28
|
+
apiKeyUrl: 'https://console.groq.com/keys',
|
|
29
|
+
apiKeyPrefix: 'gsk_',
|
|
30
|
+
apiKeyMinLength: 40,
|
|
31
|
+
envVar: 'GROQ_API_KEY',
|
|
32
|
+
free: true,
|
|
17
33
|
},
|
|
18
|
-
|
|
34
|
+
// Local providers - run AI completely on your machine
|
|
35
|
+
local: {
|
|
36
|
+
value: 'local',
|
|
37
|
+
label: 'Local Models',
|
|
38
|
+
hint: 'Run Llama, Qwen, Mistral locally - Free, private, offline',
|
|
39
|
+
category: 'local',
|
|
40
|
+
envVar: '', // No API key required
|
|
41
|
+
free: true,
|
|
42
|
+
},
|
|
43
|
+
ollama: {
|
|
44
|
+
value: 'ollama',
|
|
45
|
+
label: 'Ollama',
|
|
46
|
+
hint: 'Use Ollama server for local inference',
|
|
47
|
+
category: 'local',
|
|
48
|
+
envVar: '', // No API key required (optional OLLAMA_API_KEY for remote)
|
|
49
|
+
free: true,
|
|
50
|
+
},
|
|
51
|
+
openai: {
|
|
19
52
|
value: 'openai',
|
|
20
|
-
label: '
|
|
21
|
-
hint: '
|
|
53
|
+
label: 'OpenAI',
|
|
54
|
+
hint: 'GPT-4o, GPT-5, o1/o3 reasoning',
|
|
55
|
+
category: 'cloud',
|
|
56
|
+
apiKeyUrl: 'https://platform.openai.com/api-keys',
|
|
57
|
+
apiKeyPrefix: 'sk-',
|
|
58
|
+
apiKeyMinLength: 40,
|
|
59
|
+
envVar: 'OPENAI_API_KEY',
|
|
22
60
|
},
|
|
23
|
-
{
|
|
61
|
+
anthropic: {
|
|
24
62
|
value: 'anthropic',
|
|
25
|
-
label: '
|
|
26
|
-
hint: '
|
|
63
|
+
label: 'Anthropic',
|
|
64
|
+
hint: 'Claude 4.5, best for coding',
|
|
65
|
+
category: 'cloud',
|
|
66
|
+
apiKeyUrl: 'https://console.anthropic.com/settings/keys',
|
|
67
|
+
apiKeyPrefix: 'sk-ant-',
|
|
68
|
+
apiKeyMinLength: 40,
|
|
69
|
+
envVar: 'ANTHROPIC_API_KEY',
|
|
70
|
+
},
|
|
71
|
+
xai: {
|
|
72
|
+
value: 'xai',
|
|
73
|
+
label: 'xAI',
|
|
74
|
+
hint: 'Grok models',
|
|
75
|
+
category: 'cloud',
|
|
76
|
+
apiKeyUrl: 'https://console.x.ai/team/default/api-keys',
|
|
77
|
+
envVar: 'XAI_API_KEY',
|
|
78
|
+
},
|
|
79
|
+
cohere: {
|
|
80
|
+
value: 'cohere',
|
|
81
|
+
label: 'Cohere',
|
|
82
|
+
hint: 'Command models, RAG-optimized',
|
|
83
|
+
category: 'cloud',
|
|
84
|
+
apiKeyUrl: 'https://dashboard.cohere.com/api-keys',
|
|
85
|
+
envVar: 'COHERE_API_KEY',
|
|
86
|
+
},
|
|
87
|
+
openrouter: {
|
|
88
|
+
value: 'openrouter',
|
|
89
|
+
label: 'OpenRouter',
|
|
90
|
+
hint: '100+ models, unified API',
|
|
91
|
+
category: 'gateway',
|
|
92
|
+
apiKeyUrl: 'https://openrouter.ai/keys',
|
|
93
|
+
apiKeyPrefix: 'sk-or-',
|
|
94
|
+
apiKeyMinLength: 40,
|
|
95
|
+
envVar: 'OPENROUTER_API_KEY',
|
|
96
|
+
},
|
|
97
|
+
glama: {
|
|
98
|
+
value: 'glama',
|
|
99
|
+
label: 'Glama',
|
|
100
|
+
hint: 'OpenAI-compatible gateway',
|
|
101
|
+
category: 'gateway',
|
|
102
|
+
apiKeyUrl: 'https://glama.ai/settings/api-keys',
|
|
103
|
+
envVar: 'GLAMA_API_KEY',
|
|
104
|
+
},
|
|
105
|
+
litellm: {
|
|
106
|
+
value: 'litellm',
|
|
107
|
+
label: 'LiteLLM',
|
|
108
|
+
hint: 'Self-hosted proxy for 100+ providers',
|
|
109
|
+
category: 'gateway',
|
|
110
|
+
requiresBaseURL: true,
|
|
111
|
+
envVar: 'LITELLM_API_KEY',
|
|
27
112
|
},
|
|
28
|
-
|
|
113
|
+
'openai-compatible': {
|
|
114
|
+
value: 'openai-compatible',
|
|
115
|
+
label: 'OpenAI-Compatible',
|
|
116
|
+
hint: 'Ollama, vLLM, LocalAI, or any OpenAI-format API',
|
|
117
|
+
category: 'gateway',
|
|
118
|
+
requiresBaseURL: true,
|
|
119
|
+
envVar: 'OPENAI_COMPATIBLE_API_KEY',
|
|
120
|
+
},
|
|
121
|
+
vertex: {
|
|
122
|
+
value: 'vertex',
|
|
123
|
+
label: 'Google Vertex AI',
|
|
124
|
+
hint: 'GCP-hosted Gemini & Claude (uses ADC)',
|
|
125
|
+
category: 'enterprise',
|
|
126
|
+
apiKeyUrl: 'https://console.cloud.google.com/apis/credentials',
|
|
127
|
+
envVar: 'GOOGLE_VERTEX_PROJECT',
|
|
128
|
+
},
|
|
129
|
+
bedrock: {
|
|
130
|
+
value: 'bedrock',
|
|
131
|
+
label: 'AWS Bedrock',
|
|
132
|
+
hint: 'AWS-hosted Claude & Nova (uses AWS creds)',
|
|
133
|
+
category: 'enterprise',
|
|
134
|
+
apiKeyUrl: 'https://console.aws.amazon.com/bedrock',
|
|
135
|
+
envVar: 'AWS_ACCESS_KEY_ID',
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
/**
|
|
139
|
+
* Get providers organized by category
|
|
140
|
+
*/
|
|
141
|
+
function getProvidersByCategory() {
|
|
142
|
+
const categories = {
|
|
143
|
+
recommended: [],
|
|
144
|
+
local: [],
|
|
145
|
+
cloud: [],
|
|
146
|
+
gateway: [],
|
|
147
|
+
enterprise: [],
|
|
148
|
+
};
|
|
149
|
+
for (const provider of LLM_PROVIDERS) {
|
|
150
|
+
const option = PROVIDER_REGISTRY[provider];
|
|
151
|
+
if (option) {
|
|
152
|
+
categories[option.category].push(option);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return categories;
|
|
156
|
+
}
|
|
29
157
|
/**
|
|
30
|
-
*
|
|
31
|
-
|
|
158
|
+
* Build provider selection options with categories
|
|
159
|
+
*/
|
|
160
|
+
function buildProviderOptions() {
|
|
161
|
+
const categories = getProvidersByCategory();
|
|
162
|
+
const options = [];
|
|
163
|
+
// Recommended (free) providers first
|
|
164
|
+
if (categories.recommended.length > 0) {
|
|
165
|
+
for (const p of categories.recommended) {
|
|
166
|
+
options.push({
|
|
167
|
+
value: p.value,
|
|
168
|
+
label: `${chalk.green('●')} ${p.label}`,
|
|
169
|
+
hint: `${p.hint} ${chalk.green('(free)')}`,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// Local providers - run AI on your machine
|
|
174
|
+
if (categories.local.length > 0) {
|
|
175
|
+
for (const p of categories.local) {
|
|
176
|
+
options.push({
|
|
177
|
+
value: p.value,
|
|
178
|
+
label: `${chalk.cyan('●')} ${p.label}`,
|
|
179
|
+
hint: `${p.hint} ${chalk.cyan('(local)')}`,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// Cloud providers
|
|
184
|
+
if (categories.cloud.length > 0) {
|
|
185
|
+
for (const p of categories.cloud) {
|
|
186
|
+
options.push({
|
|
187
|
+
value: p.value,
|
|
188
|
+
label: `${chalk.blue('●')} ${p.label}`,
|
|
189
|
+
hint: p.hint,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// Gateway providers
|
|
194
|
+
if (categories.gateway.length > 0) {
|
|
195
|
+
for (const p of categories.gateway) {
|
|
196
|
+
const suffix = p.requiresBaseURL ? chalk.gray(' (requires URL)') : '';
|
|
197
|
+
options.push({
|
|
198
|
+
value: p.value,
|
|
199
|
+
label: `${chalk.rgb(255, 165, 0)('●')} ${p.label}`,
|
|
200
|
+
hint: `${p.hint}${suffix}`,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
// Enterprise providers
|
|
205
|
+
if (categories.enterprise.length > 0) {
|
|
206
|
+
for (const p of categories.enterprise) {
|
|
207
|
+
options.push({
|
|
208
|
+
value: p.value,
|
|
209
|
+
label: `${chalk.cyan('●')} ${p.label}`,
|
|
210
|
+
hint: p.hint,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return options;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Interactive provider selection with back option.
|
|
218
|
+
* @returns Selected provider, '_back' if back selected, or null if cancelled
|
|
32
219
|
*/
|
|
33
220
|
export async function selectProvider() {
|
|
221
|
+
const options = buildProviderOptions();
|
|
34
222
|
const choice = await p.select({
|
|
35
223
|
message: 'Choose your AI provider',
|
|
36
|
-
options:
|
|
224
|
+
options: [
|
|
225
|
+
...options,
|
|
226
|
+
{
|
|
227
|
+
value: '_back',
|
|
228
|
+
label: chalk.gray('← Back'),
|
|
229
|
+
hint: 'Return to previous menu',
|
|
230
|
+
},
|
|
231
|
+
],
|
|
37
232
|
});
|
|
38
233
|
if (p.isCancel(choice)) {
|
|
39
|
-
|
|
40
|
-
process.exit(1);
|
|
234
|
+
return null;
|
|
41
235
|
}
|
|
42
236
|
return choice;
|
|
43
237
|
}
|
|
44
238
|
/**
|
|
45
|
-
*
|
|
239
|
+
* Get provider display name
|
|
46
240
|
*/
|
|
47
241
|
export function getProviderDisplayName(provider) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
242
|
+
return PROVIDER_REGISTRY[provider]?.label || provider;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Get provider option info
|
|
246
|
+
*/
|
|
247
|
+
export function getProviderInfo(provider) {
|
|
248
|
+
return PROVIDER_REGISTRY[provider];
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Legacy PROVIDER_OPTIONS for backwards compatibility with init-app
|
|
252
|
+
*/
|
|
253
|
+
export const PROVIDER_OPTIONS = buildProviderOptions();
|
|
254
|
+
/**
|
|
255
|
+
* Get API key format hint for a provider
|
|
256
|
+
*/
|
|
257
|
+
export function getApiKeyFormatHint(provider) {
|
|
258
|
+
const info = PROVIDER_REGISTRY[provider];
|
|
259
|
+
if (!info?.apiKeyPrefix)
|
|
260
|
+
return null;
|
|
261
|
+
return `Key should start with "${info.apiKeyPrefix}"`;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Validates API key format for a provider with detailed error messages
|
|
265
|
+
*/
|
|
266
|
+
export function validateApiKeyFormat(apiKey, provider) {
|
|
267
|
+
const info = PROVIDER_REGISTRY[provider];
|
|
268
|
+
const trimmed = apiKey.trim();
|
|
269
|
+
if (!trimmed) {
|
|
270
|
+
return { valid: false, error: 'API key cannot be empty' };
|
|
271
|
+
}
|
|
272
|
+
// Check minimum length if specified
|
|
273
|
+
if (info?.apiKeyMinLength && trimmed.length < info.apiKeyMinLength) {
|
|
274
|
+
return {
|
|
275
|
+
valid: false,
|
|
276
|
+
error: `API key seems too short (expected ${info.apiKeyMinLength}+ characters, got ${trimmed.length})`,
|
|
277
|
+
};
|
|
59
278
|
}
|
|
279
|
+
// Check prefix if specified
|
|
280
|
+
if (info?.apiKeyPrefix && !trimmed.startsWith(info.apiKeyPrefix)) {
|
|
281
|
+
const prefixLen = info.apiKeyPrefix.length;
|
|
282
|
+
return {
|
|
283
|
+
valid: false,
|
|
284
|
+
error: `Invalid format: ${getProviderDisplayName(provider)} keys start with "${info.apiKeyPrefix}" (got "${trimmed.slice(0, prefixLen)}...")`,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
return { valid: true };
|
|
60
288
|
}
|
|
61
289
|
/**
|
|
62
|
-
*
|
|
290
|
+
* Legacy validation function for backwards compatibility
|
|
63
291
|
*/
|
|
64
292
|
export function isValidApiKeyFormat(apiKey, provider) {
|
|
65
|
-
|
|
66
|
-
case 'google':
|
|
67
|
-
return apiKey.startsWith('AIza') && apiKey.length > 20;
|
|
68
|
-
case 'openai':
|
|
69
|
-
return apiKey.startsWith('sk-') && apiKey.length > 40;
|
|
70
|
-
case 'anthropic':
|
|
71
|
-
return apiKey.startsWith('sk-ant-') && apiKey.length > 40;
|
|
72
|
-
case 'groq':
|
|
73
|
-
return apiKey.startsWith('gsk_') && apiKey.length > 40;
|
|
74
|
-
default:
|
|
75
|
-
return apiKey.length > 10; // Basic length check
|
|
76
|
-
}
|
|
293
|
+
return validateApiKeyFormat(apiKey, provider).valid;
|
|
77
294
|
}
|
|
78
295
|
/**
|
|
79
296
|
* Gets provider-specific instructions for API key setup
|
|
80
297
|
*/
|
|
81
298
|
export function getProviderInstructions(provider) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
content: `1. Visit: ${chalk.cyan('https://console.groq.com/keys')}\n` +
|
|
114
|
-
`2. Sign in with your account\n` +
|
|
115
|
-
`3. Click "Create API Key"\n` +
|
|
116
|
-
`4. Copy the key\n\n` +
|
|
117
|
-
`${chalk.dim('🆓 Free tier included')}`,
|
|
118
|
-
};
|
|
119
|
-
default:
|
|
120
|
-
return null;
|
|
299
|
+
const info = PROVIDER_REGISTRY[provider];
|
|
300
|
+
if (!info)
|
|
301
|
+
return null;
|
|
302
|
+
const freeTag = info.free ? chalk.green(' (Free)') : '';
|
|
303
|
+
const title = `${getProviderDisplayName(provider)} API Key${freeTag}`;
|
|
304
|
+
let content = '';
|
|
305
|
+
if (info.apiKeyUrl) {
|
|
306
|
+
content += `1. Visit: ${chalk.cyan(info.apiKeyUrl)}\n`;
|
|
307
|
+
content += `2. Sign in to your account\n`;
|
|
308
|
+
content += `3. Create a new API key\n`;
|
|
309
|
+
content += `4. Copy and paste it below\n`;
|
|
310
|
+
}
|
|
311
|
+
else if (info.requiresBaseURL) {
|
|
312
|
+
content += `This provider requires a custom endpoint URL.\n`;
|
|
313
|
+
content += `You'll configure both the URL and API key in the next steps.\n`;
|
|
314
|
+
}
|
|
315
|
+
if (info.apiKeyPrefix) {
|
|
316
|
+
content += `\n${chalk.gray(`Key format: ${info.apiKeyPrefix}...`)}`;
|
|
317
|
+
}
|
|
318
|
+
return { title, content, url: info.apiKeyUrl };
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Open the API key URL in the browser
|
|
322
|
+
*/
|
|
323
|
+
export async function openApiKeyUrl(provider) {
|
|
324
|
+
const info = PROVIDER_REGISTRY[provider];
|
|
325
|
+
if (!info?.apiKeyUrl)
|
|
326
|
+
return false;
|
|
327
|
+
try {
|
|
328
|
+
await open(info.apiKeyUrl);
|
|
329
|
+
return true;
|
|
121
330
|
}
|
|
331
|
+
catch {
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Check if provider requires a base URL
|
|
337
|
+
*/
|
|
338
|
+
export function providerRequiresBaseURL(provider) {
|
|
339
|
+
return PROVIDER_REGISTRY[provider]?.requiresBaseURL === true;
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Get default model for provider, with fallback for custom providers
|
|
343
|
+
*/
|
|
344
|
+
export function getDefaultModel(provider) {
|
|
345
|
+
const defaultModel = getDefaultModelForProvider(provider);
|
|
346
|
+
if (defaultModel)
|
|
347
|
+
return defaultModel;
|
|
348
|
+
// Fallback for providers without a default (custom providers)
|
|
349
|
+
const providerInfo = LLM_REGISTRY[provider];
|
|
350
|
+
if (providerInfo?.models && providerInfo.models.length > 0) {
|
|
351
|
+
return providerInfo.models[0].name;
|
|
352
|
+
}
|
|
353
|
+
// For providers that accept any model, return empty to prompt user
|
|
354
|
+
return '';
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Get environment variable name for provider's API key.
|
|
358
|
+
* Uses the canonical env var from the core api-key-resolver.
|
|
359
|
+
*/
|
|
360
|
+
export function getProviderEnvVar(provider) {
|
|
361
|
+
return getPrimaryApiKeyEnvVar(provider);
|
|
122
362
|
}
|