diff --git a/src/vs/workbench/contrib/void/browser/react/src/void-onboarding/VoidOnboarding.tsx b/src/vs/workbench/contrib/void/browser/react/src/void-onboarding/VoidOnboarding.tsx index 7bf94b47..d03556a1 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/void-onboarding/VoidOnboarding.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/void-onboarding/VoidOnboarding.tsx @@ -6,7 +6,7 @@ import { useEffect, useRef, useState } from 'react'; import { useAccessor, useIsDark, useSettingsState } from '../util/services.js'; import { Brain, Check, ChevronRight, DollarSign, ExternalLink, Lock, X } from 'lucide-react'; -import { displayInfoOfProviderName, ProviderName, providerNames, localProviderNames, featureNames, FeatureName } from '../../../../common/voidSettingsTypes.js'; +import { displayInfoOfProviderName, ProviderName, providerNames, localProviderNames, featureNames, FeatureName, isFeatureNameDisabled } from '../../../../common/voidSettingsTypes.js'; import { ChatMarkdownRender } from '../markdown/ChatMarkdownRender.js'; import { OllamaSetupInstructions, OneClickSwitchButton, SettingsForProvider, ModelDump } from '../void-settings-tsx/Settings.js'; import { ColorScheme } from '../../../../../../../platform/theme/common/theme.js'; @@ -113,21 +113,10 @@ const providerNamesOfTab: Record = { const descriptionOfTab: Record = { Free: `Providers with a 100% free tier. Add as many as you'd like!`, Paid: `Connect directly with any provider (bring your own key).`, - Local: `Add as many local providers as you'd like! Running providers should appear automatically.`, + Local: `Add as many local providers as you'd like! Active providers should appear automatically.`, 'Cloud/Other': `Reach out for custom configuration requests.`, }; -const subtextMdOfTab: Record = { - Free: ` -Gemini 2.5 Pro offers 25 free messages a day, and Gemini 2.5 Flash offers 500. -We recommend using models down the line as you run out of free credits. More information [here](https://ai.google.dev/gemini-api/docs/rate-limits#current-rate-limits). - -OpenRouter offers 50 free messages a day, and that increases to 1000 if you deposit $10. Only applies to models labeled \`:free\`. More information [here](https://openrouter.ai/docs/api-reference/limits). -`, - Paid: null, - Local: null, - 'Cloud/Other': null, -}; const featureNameMap: { display: string, featureName: FeatureName }[] = [ { display: 'Chat', featureName: 'Chat' }, @@ -139,6 +128,7 @@ const featureNameMap: { display: string, featureName: FeatureName }[] = [ const AddProvidersPage = ({ pageIndex, setPageIndex }: { pageIndex: number, setPageIndex: (index: number) => void }) => { const [currentTab, setCurrentTab] = useState('Free'); const settingsState = useSettingsState(); + const [errorMessage, setErrorMessage] = useState(null); return (
@@ -153,7 +143,10 @@ const AddProvidersPage = ({ pageIndex, setPageIndex }: { pageIndex: number, setP ? 'bg-[#0e70c0]/80 text-white font-medium shadow-sm' : 'bg-void-bg-2 hover:bg-void-bg-2/80 text-void-fg-1' } transition-all duration-200`} - onClick={() => setCurrentTab(tab as TabName)} + onClick={() => { + setCurrentTab(tab as TabName); + setErrorMessage(null); // Reset error message when changing tabs + }} > {tab} @@ -161,12 +154,18 @@ const AddProvidersPage = ({ pageIndex, setPageIndex }: { pageIndex: number, setP
{/* Feature Checklist */} -
+
{featureNameMap.map(({ display, featureName }) => { const hasModel = settingsState.modelSelectionOfFeature[featureName] !== null; return (
- {hasModel ? : } + {hasModel ? ( + + ) : ( +
+
+
+ )} {display}
); @@ -178,9 +177,6 @@ const AddProvidersPage = ({ pageIndex, setPageIndex }: { pageIndex: number, setP
{currentTab}
{descriptionOfTab[currentTab]}
- {subtextMdOfTab[currentTab] ?
- -
: null} {providerNamesOfTab[currentTab].map((providerName) => (
@@ -191,18 +187,58 @@ const AddProvidersPage = ({ pageIndex, setPageIndex }: { pageIndex: number, setP ))} {(currentTab === 'Local' || currentTab === 'Cloud/Other') && ( -
-
Models
+
+
+
Models
+
+
+ + {currentTab === 'Local' && ( +
+ Local models should be detected automatically. You can add custom models below. +
+ )} + {currentTab === 'Local' && } {currentTab === 'Cloud/Other' && }
)} + + {currentTab === 'Free' &&
+ +
+
+
+
+
+ } {/* Navigation buttons in right column */} -
+
+ {errorMessage && ( +
{errorMessage}
+ )}
setPageIndex(pageIndex - 1)} /> - setPageIndex(pageIndex + 1)} /> + { + const isDisabled = isFeatureNameDisabled('Chat', settingsState) + + if (!isDisabled) { + setPageIndex(pageIndex + 1); + setErrorMessage(null); + } else { + // Show error message + setErrorMessage("Please set up at least one Chat model first."); + } + }} + />
diff --git a/src/vs/workbench/contrib/void/browser/sidebarActions.ts b/src/vs/workbench/contrib/void/browser/sidebarActions.ts index ac5513fe..72e5bf17 100644 --- a/src/vs/workbench/contrib/void/browser/sidebarActions.ts +++ b/src/vs/workbench/contrib/void/browser/sidebarActions.ts @@ -129,7 +129,7 @@ registerAction2(class extends Action2 { uri: model.uri, language: model.getLanguageId(), range: [selectionRange.startLineNumber, selectionRange.endLineNumber], - state: { wasAddedAsCurrentFile: false } + state: { wasAddedAsCurrentFile: false }, }) await chatThreadService.focusCurrentChat() @@ -196,7 +196,7 @@ registerAction2(class extends Action2 { uri: model.uri, language: model.getLanguageId(), range: [selectionRange.startLineNumber, selectionRange.endLineNumber], - state: { wasAddedAsCurrentFile: false } + state: { wasAddedAsCurrentFile: false }, }) } }) diff --git a/src/vs/workbench/contrib/void/common/voidSettingsTypes.ts b/src/vs/workbench/contrib/void/common/voidSettingsTypes.ts index dcae2587..d7ba0024 100644 --- a/src/vs/workbench/contrib/void/common/voidSettingsTypes.ts +++ b/src/vs/workbench/contrib/void/common/voidSettingsTypes.ts @@ -92,7 +92,7 @@ export const displayInfoOfProviderName = (providerName: ProviderName): DisplayIn return { title: 'Groq', } } else if (providerName === 'xAI') { - return { title: 'xAI', } + return { title: 'Grok', } } else if (providerName === 'mistral') { return { title: 'Mistral', } @@ -120,9 +120,9 @@ export const subTextMdOfProviderName = (providerName: ProviderName): string => { if (providerName === 'openAICompatible') return `Use any provider that's OpenAI-compatible (use this for llama.cpp and more).` if (providerName === 'googleVertex') return 'You must authenticate before using Vertex with Void. Read more about endpoints [here](https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/call-vertex-using-openai-library), and regions [here](https://cloud.google.com/vertex-ai/docs/general/locations#available-regions).' if (providerName === 'microsoftAzure') return 'Read more about endpoints [here](https://learn.microsoft.com/en-us/rest/api/aifoundry/model-inference/get-chat-completions/get-chat-completions?view=rest-aifoundry-model-inference-2024-05-01-preview&tabs=HTTP), and get your API key [here](https://learn.microsoft.com/en-us/azure/search/search-security-api-keys?tabs=rest-use%2Cportal-find%2Cportal-query#find-existing-keys).' - if (providerName === 'ollama') return 'If you would like to change this endpoint, please read more about [Endpoints here](https://github.com/ollama/ollama/blob/main/docs/faq.md#how-can-i-expose-ollama-on-my-network).' - if (providerName === 'vLLM') return 'If you would like to change this endpoint, please read more about [Endpoints here](https://docs.vllm.ai/en/latest/getting_started/quickstart.html#openai-compatible-server).' - if (providerName === 'lmStudio') return 'If you would like to change this endpoint, please more about [Endpoints here](https://lmstudio.ai/docs/app/api/endpoints/openai).' + if (providerName === 'ollama') return 'Read more about custom [Endpoints here](https://github.com/ollama/ollama/blob/main/docs/faq.md#how-can-i-expose-ollama-on-my-network).' + if (providerName === 'vLLM') return 'Read more about custom [Endpoints here](https://docs.vllm.ai/en/latest/getting_started/quickstart.html#openai-compatible-server).' + if (providerName === 'lmStudio') return 'Read more about custom [Endpoints here](https://lmstudio.ai/docs/app/api/endpoints/openai).' if (providerName === 'liteLLM') return 'Read more about endpoints [here](https://docs.litellm.ai/docs/providers/openai_compatible).' throw new Error(`subTextMdOfProviderName: Unknown provider name: "${providerName}"`)