mirror of
https://github.com/voideditor/void
synced 2026-05-23 09:28:23 +00:00
Merge pull request #406 from voideditor/model-selection
Onboarding, SSH
This commit is contained in:
commit
f09f538b05
17 changed files with 588 additions and 365 deletions
|
|
@ -86,7 +86,7 @@ function prepareDebPackage(arch) {
|
|||
const dependencies = await dependenciesGenerator.getDependencies('deb', binaryDir, product.applicationName, debArch);
|
||||
gulp.src('resources/linux/debian/control.template', { base: '.' })
|
||||
.pipe(replace('@@NAME@@', product.applicationName))
|
||||
.pipe(replace('@@VERSION@@', `${packageJson.version}.${packageJson.release}`))
|
||||
.pipe(replace('@@VERSION@@', `${product.voidVersion}.${packageJson.release}`))
|
||||
.pipe(replace('@@ARCHITECTURE@@', debArch))
|
||||
.pipe(replace('@@DEPENDS@@', dependencies.join(', ')))
|
||||
.pipe(replace('@@RECOMMENDS@@', debianRecommendedDependencies.join(', ')))
|
||||
|
|
@ -201,7 +201,7 @@ function prepareRpmPackage(arch) {
|
|||
.pipe(replace('@@NAME@@', product.applicationName))
|
||||
.pipe(replace('@@NAME_LONG@@', product.nameLong))
|
||||
.pipe(replace('@@ICON@@', product.linuxIconName))
|
||||
.pipe(replace('@@VERSION@@', `${packageJson.version}.${packageJson.release}`))
|
||||
.pipe(replace('@@VERSION@@', `${product.voidVersion}.${packageJson.release}`))
|
||||
.pipe(replace('@@ARCHITECTURE@@', rpmArch))
|
||||
.pipe(replace('@@LICENSE@@', product.licenseName))
|
||||
.pipe(replace('@@QUALITY@@', product.quality || '@@QUALITY@@'))
|
||||
|
|
@ -277,7 +277,7 @@ function prepareSnapPackage(arch) {
|
|||
|
||||
const snapcraft = gulp.src('resources/linux/snap/snapcraft.yaml', { base: '.' })
|
||||
.pipe(replace('@@NAME@@', product.applicationName))
|
||||
.pipe(replace('@@VERSION@@', `${packageJson.version}.${packageJson.release}`))
|
||||
.pipe(replace('@@VERSION@@', `${product.voidVersion}.${packageJson.release}`))
|
||||
// Possible run-on values https://snapcraft.io/docs/architectures
|
||||
.pipe(replace('@@ARCHITECTURE@@', arch === 'x64' ? 'amd64' : arch))
|
||||
.pipe(rename('snap/snapcraft.yaml'));
|
||||
|
|
|
|||
|
|
@ -22,10 +22,12 @@ import { ColorScheme } from '../../web.api.js';
|
|||
import { OpenFileFolderAction, OpenFolderAction } from '../../actions/workspaceActions.js';
|
||||
import { IWindowOpenable } from '../../../../platform/window/common/window.js';
|
||||
import { splitRecentLabel } from '../../../../base/common/labels.js';
|
||||
import { IViewsService } from '../../../services/views/common/viewsService.js';
|
||||
|
||||
/* eslint-disable */ // Void
|
||||
import { VOID_CTRL_K_ACTION_ID, VOID_CTRL_L_ACTION_ID } from '../../../contrib/void/browser/actionIDs.js';
|
||||
import { VOID_OPEN_SETTINGS_ACTION_ID } from '../../../contrib/void/browser/voidSettingsPane.js';
|
||||
import { VIEWLET_ID as REMOTE_EXPLORER_VIEWLET_ID } from '../../../contrib/remote/browser/remoteExplorer.js';
|
||||
/* eslint-enable */
|
||||
|
||||
// interface WatermarkEntry {
|
||||
|
|
@ -98,6 +100,7 @@ export class EditorGroupWatermark extends Disposable {
|
|||
@ICommandService private readonly commandService: ICommandService,
|
||||
@IHostService private readonly hostService: IHostService,
|
||||
@ILabelService private readonly labelService: ILabelService,
|
||||
@IViewsService private readonly viewsService: IViewsService,
|
||||
) {
|
||||
super();
|
||||
|
||||
|
|
@ -182,14 +185,21 @@ export class EditorGroupWatermark extends Disposable {
|
|||
// Void - if the workbench is empty, show open
|
||||
if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) {
|
||||
|
||||
// Create a flex container for buttons with vertical direction
|
||||
const buttonContainer = $('div');
|
||||
buttonContainer.style.display = 'flex';
|
||||
buttonContainer.style.flexDirection = 'column'; // Change to column for vertical stacking
|
||||
buttonContainer.style.alignItems = 'center'; // Center the buttons horizontally
|
||||
buttonContainer.style.gap = '8px'; // Reduce gap between buttons from 16px to 8px
|
||||
buttonContainer.style.marginBottom = '16px';
|
||||
voidIconBox.appendChild(buttonContainer);
|
||||
|
||||
// Open a folder
|
||||
const openFolderButton = h('button')
|
||||
openFolderButton.root.classList.add('void-watermark-button')
|
||||
openFolderButton.root.classList.add('void-openfolder-button')
|
||||
openFolderButton.root.style.display = 'block'
|
||||
openFolderButton.root.style.marginLeft = 'auto'
|
||||
openFolderButton.root.style.marginRight = 'auto'
|
||||
openFolderButton.root.style.marginBottom = '16px'
|
||||
openFolderButton.root.textContent = 'Open a folder'
|
||||
openFolderButton.root.style.width = '124px' // Set width to 124px as requested
|
||||
openFolderButton.root.textContent = 'Open Folder'
|
||||
openFolderButton.root.onclick = () => {
|
||||
this.commandService.executeCommand(isMacintosh && isNative ? OpenFileFolderAction.ID : OpenFolderAction.ID)
|
||||
// if (this.contextKeyService.contextMatchesRules(ContextKeyExpr.and(WorkbenchStateContext.isEqualTo('workspace')))) {
|
||||
|
|
@ -198,7 +208,19 @@ export class EditorGroupWatermark extends Disposable {
|
|||
// this.commandService.executeCommand(isMacintosh ? 'workbench.action.files.openFileFolder' : 'workbench.action.files.openFolder');
|
||||
// }
|
||||
}
|
||||
voidIconBox.appendChild(openFolderButton.root);
|
||||
buttonContainer.appendChild(openFolderButton.root);
|
||||
|
||||
// Open SSH button
|
||||
const openSSHButton = h('button')
|
||||
openSSHButton.root.classList.add('void-openssh-button')
|
||||
openSSHButton.root.style.display = 'block'
|
||||
openSSHButton.root.style.backgroundColor = '#5a5a5a' // Made darker than the default gray
|
||||
openSSHButton.root.style.width = '124px' // Set width to 124px as requested
|
||||
openSSHButton.root.textContent = 'Open SSH'
|
||||
openSSHButton.root.onclick = () => {
|
||||
this.viewsService.openViewContainer(REMOTE_EXPLORER_VIEWLET_ID);
|
||||
}
|
||||
buttonContainer.appendChild(openSSHButton.root);
|
||||
|
||||
|
||||
// Recents
|
||||
|
|
@ -244,6 +266,9 @@ export class EditorGroupWatermark extends Disposable {
|
|||
|
||||
const dirSpan = $('span');
|
||||
dirSpan.style.paddingLeft = '4px';
|
||||
dirSpan.style.whiteSpace = 'nowrap';
|
||||
dirSpan.style.overflow = 'hidden';
|
||||
dirSpan.style.maxWidth = '300px';
|
||||
dirSpan.innerText = parentPath;
|
||||
dirSpan.title = fullPath;
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
}
|
||||
|
||||
/* light */
|
||||
.void-void-icon,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .editor-group-watermark > .letterpress {
|
||||
width: 100%;
|
||||
max-height: 100%;
|
||||
|
|
@ -60,14 +61,17 @@
|
|||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.void-void-icon,
|
||||
.monaco-workbench.vs-dark .part.editor > .content .editor-group-container .editor-group-watermark > .letterpress {
|
||||
background-image: url('./void_cube_noshadow.png'); /* // Void */
|
||||
}
|
||||
|
||||
.void-void-icon,
|
||||
.monaco-workbench.hc-light .part.editor > .content .editor-group-container .editor-group-watermark > .letterpress {
|
||||
background-image: url('./void_cube_noshadow.png'); /* // Void */
|
||||
}
|
||||
|
||||
.void-void-icon,
|
||||
.monaco-workbench.hc-black .part.editor > .content .editor-group-container .editor-group-watermark > .letterpress {
|
||||
background-image: url('./void_cube_noshadow.png'); /* // Void */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -792,7 +792,6 @@ export class AutocompleteService extends Disposable implements IAutocompleteServ
|
|||
const featureName: FeatureName = 'Autocomplete'
|
||||
const modelSelection = this._settingsService.state.modelSelectionOfFeature[featureName]
|
||||
const modelSelectionOptions = modelSelection ? this._settingsService.state.optionsOfModelSelection[featureName][modelSelection.providerName]?.[modelSelection.modelName] : undefined
|
||||
const aiInstructions = this._settingsService.state.globalSettings.aiInstructions
|
||||
|
||||
// set parameters of `newAutocompletion` appropriately
|
||||
newAutocompletion.llmPromise = new Promise((resolve, reject) => {
|
||||
|
|
@ -804,8 +803,7 @@ export class AutocompleteService extends Disposable implements IAutocompleteServ
|
|||
prefix: llmPrefix,
|
||||
suffix: llmSuffix,
|
||||
stopTokens: stopTokens,
|
||||
},
|
||||
aiInstructions
|
||||
}
|
||||
}),
|
||||
modelSelection,
|
||||
modelSelectionOptions,
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ import { IVoidSettingsService } from '../common/voidSettingsService.js';
|
|||
import { ChatMode, FeatureName, ModelSelection } from '../common/voidSettingsTypes.js';
|
||||
import { IDirectoryStrService } from './directoryStrService.js';
|
||||
import { ITerminalToolService } from './terminalToolService.js';
|
||||
import { IVoidModelService } from '../common/voidModelService.js';
|
||||
import { URI } from '../../../../base/common/uri.js';
|
||||
|
||||
|
||||
|
||||
|
|
@ -412,9 +414,9 @@ const prepareMessages = ({
|
|||
|
||||
export interface IConvertToLLMMessageService {
|
||||
readonly _serviceBrand: undefined;
|
||||
prepareLLMSimpleMessages: (opts: { simpleMessages: SimpleLLMMessage[], systemMessage: string, modelSelection: ModelSelection | null, featureName: FeatureName }) => { messages: LLMChatMessage[], separateSystemMessage: string | undefined };
|
||||
prepareLLMSimpleMessages: (opts: { simpleMessages: SimpleLLMMessage[], systemMessage: string, modelSelection: ModelSelection | null, featureName: FeatureName }) => { messages: LLMChatMessage[], separateSystemMessage: string | undefined }
|
||||
prepareLLMChatMessages: (opts: { chatMessages: ChatMessage[], chatMode: ChatMode, modelSelection: ModelSelection | null }) => Promise<{ messages: LLMChatMessage[], separateSystemMessage: string | undefined }>
|
||||
prepareFIMMessage(opts: { messages: LLMFIMMessage, aiInstructions: string, }): { prefix: string, suffix: string, stopTokens: string[] }
|
||||
prepareFIMMessage(opts: { messages: LLMFIMMessage, }): { prefix: string, suffix: string, stopTokens: string[] }
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -431,10 +433,35 @@ class ConvertToLLMMessageService extends Disposable implements IConvertToLLMMess
|
|||
@IDirectoryStrService private readonly directoryStrService: IDirectoryStrService,
|
||||
@ITerminalToolService private readonly terminalToolService: ITerminalToolService,
|
||||
@IVoidSettingsService private readonly voidSettingsService: IVoidSettingsService,
|
||||
@IVoidModelService private readonly voidModelService: IVoidModelService,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
// Read .voidinstructions files from workspace folders
|
||||
private _getVoidInstructionsFileContents(): string {
|
||||
const workspaceFolders = this.workspaceContextService.getWorkspace().folders;
|
||||
let voidInstructions = '';
|
||||
for (const folder of workspaceFolders) {
|
||||
const uri = URI.joinPath(folder.uri, '.voidinstructions')
|
||||
const { model } = this.voidModelService.getModel(uri)
|
||||
if (!model) continue
|
||||
voidInstructions += model.getValue() + '\n\n';
|
||||
}
|
||||
return voidInstructions.trim();
|
||||
}
|
||||
|
||||
// Get combined AI instructions from settings and .voidinstructions files
|
||||
private _getCombinedAIInstructions(): string {
|
||||
const globalAIInstructions = this.voidSettingsService.state.globalSettings.aiInstructions;
|
||||
const voidInstructionsFileContent = this._getVoidInstructionsFileContents();
|
||||
|
||||
const ans: string[] = []
|
||||
if (globalAIInstructions) ans.push(globalAIInstructions)
|
||||
if (voidInstructionsFileContent) ans.push(voidInstructionsFileContent)
|
||||
return ans.join('\n\n')
|
||||
}
|
||||
|
||||
|
||||
// system message
|
||||
private _generateChatMessagesSystemMessage = async (chatMode: ChatMode, specialToolFormat: 'openai-style' | 'anthropic-style' | undefined) => {
|
||||
|
|
@ -502,7 +529,9 @@ class ConvertToLLMMessageService extends Disposable implements IConvertToLLMMess
|
|||
} = getModelCapabilities(providerName, modelName)
|
||||
|
||||
const modelSelectionOptions = this.voidSettingsService.state.optionsOfModelSelection[featureName][modelSelection.providerName]?.[modelSelection.modelName]
|
||||
const aiInstructions = this.voidSettingsService.state.globalSettings.aiInstructions
|
||||
|
||||
// Get combined AI instructions
|
||||
const aiInstructions = this._getCombinedAIInstructions();
|
||||
|
||||
const isReasoningEnabled = getIsReasoningEnabledState(featureName, providerName, modelName, modelSelectionOptions)
|
||||
const maxOutputTokens = getMaxOutputTokens(providerName, modelName, { isReasoningEnabled })
|
||||
|
|
@ -518,7 +547,6 @@ class ConvertToLLMMessageService extends Disposable implements IConvertToLLMMess
|
|||
maxOutputTokens,
|
||||
})
|
||||
return { messages, separateSystemMessage };
|
||||
|
||||
}
|
||||
prepareLLMChatMessages: IConvertToLLMMessageService['prepareLLMChatMessages'] = async ({ chatMessages, chatMode, modelSelection }) => {
|
||||
if (modelSelection === null) return { messages: [], separateSystemMessage: undefined }
|
||||
|
|
@ -531,7 +559,9 @@ class ConvertToLLMMessageService extends Disposable implements IConvertToLLMMess
|
|||
const systemMessage = await this._generateChatMessagesSystemMessage(chatMode, specialToolFormat)
|
||||
|
||||
const modelSelectionOptions = this.voidSettingsService.state.optionsOfModelSelection['Chat'][modelSelection.providerName]?.[modelSelection.modelName]
|
||||
const aiInstructions = this.voidSettingsService.state.globalSettings.aiInstructions
|
||||
|
||||
// Get combined AI instructions
|
||||
const aiInstructions = this._getCombinedAIInstructions();
|
||||
|
||||
const isReasoningEnabled = getIsReasoningEnabledState('Chat', providerName, modelName, modelSelectionOptions)
|
||||
const maxOutputTokens = getMaxOutputTokens(providerName, modelName, { isReasoningEnabled })
|
||||
|
|
@ -548,19 +578,20 @@ class ConvertToLLMMessageService extends Disposable implements IConvertToLLMMess
|
|||
maxOutputTokens,
|
||||
})
|
||||
return { messages, separateSystemMessage };
|
||||
|
||||
}
|
||||
|
||||
|
||||
// --- FIM ---
|
||||
|
||||
prepareFIMMessage: IConvertToLLMMessageService['prepareFIMMessage'] = ({ messages, aiInstructions }) => {
|
||||
prepareFIMMessage: IConvertToLLMMessageService['prepareFIMMessage'] = ({ messages }) => {
|
||||
// Get combined AI instructions with the provided aiInstructions as the base
|
||||
const combinedInstructions = this._getCombinedAIInstructions();
|
||||
|
||||
let prefix = `\
|
||||
${!aiInstructions ? '' : `\
|
||||
${!combinedInstructions ? '' : `\
|
||||
// Instructions:
|
||||
// Do not output an explanation. Try to avoid outputting comments. Only output the middle code.
|
||||
${aiInstructions.split('\n').map(line => `//${line}`).join('\n')}`}
|
||||
${combinedInstructions.split('\n').map(line => `//${line}`).join('\n')}`}
|
||||
|
||||
${messages.prefix}`
|
||||
|
||||
|
|
@ -573,7 +604,6 @@ ${messages.prefix}`
|
|||
}
|
||||
|
||||
|
||||
// pick one and delete the other:
|
||||
registerSingleton(IConvertToLLMMessageService, ConvertToLLMMessageService, InstantiationType.Eager);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
/*--------------------------------------------------------------------------------------
|
||||
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
|
||||
*--------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Disposable } from '../../../../base/common/lifecycle.js';
|
||||
import { URI } from '../../../../base/common/uri.js';
|
||||
import { IWorkspaceContextService } from '../../../../platform/workspace/common/workspace.js';
|
||||
import { IWorkbenchContribution, registerWorkbenchContribution2, WorkbenchPhase } from '../../../common/contributions.js';
|
||||
import { IVoidModelService } from '../common/voidModelService.js';
|
||||
|
||||
class ConvertContribWorkbenchContribution extends Disposable implements IWorkbenchContribution {
|
||||
static readonly ID = 'workbench.contrib.void.convertcontrib'
|
||||
_serviceBrand: undefined;
|
||||
|
||||
constructor(
|
||||
@IVoidModelService private readonly voidModelService: IVoidModelService,
|
||||
@IWorkspaceContextService private readonly workspaceContext: IWorkspaceContextService,
|
||||
) {
|
||||
super()
|
||||
|
||||
const initializeURI = (uri: URI) => {
|
||||
this.workspaceContext.getWorkspace()
|
||||
const voidInstrsURI = URI.joinPath(uri, '.voidinstructions')
|
||||
this.voidModelService.initializeModel(voidInstrsURI)
|
||||
}
|
||||
|
||||
// call
|
||||
this._register(this.workspaceContext.onDidChangeWorkspaceFolders((e) => {
|
||||
[...e.changed, ...e.added].forEach(w => { initializeURI(w.uri) })
|
||||
}))
|
||||
this.workspaceContext.getWorkspace().folders.forEach(w => { initializeURI(w.uri) })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
registerWorkbenchContribution2(ConvertContribWorkbenchContribution.ID, ConvertContribWorkbenchContribution, WorkbenchPhase.BlockRestore);
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
|
||||
*--------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-editor .void-sweepIdxBG {
|
||||
.monaco-editor .void-sweepIdxBG {
|
||||
background-color: var(--vscode-void-sweepIdxBG);
|
||||
}
|
||||
|
||||
|
|
@ -23,10 +23,30 @@
|
|||
background-color: var(--vscode-void-redBG);
|
||||
}
|
||||
|
||||
.void-watermark-button {
|
||||
margin: 8px 0;
|
||||
|
||||
/* Renamed from void-watermark-button to void-openfolder-button */
|
||||
.void-openfolder-button {
|
||||
padding: 8px 20px;
|
||||
background-color: #3b82f6;
|
||||
background-color: #306dce;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
outline: none !important;
|
||||
box-shadow: none !important;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
.void-openfolder-button:hover {
|
||||
background-color: #2563eb;
|
||||
}
|
||||
.void-openfolder-button:active {
|
||||
background-color: #2563eb;
|
||||
}
|
||||
|
||||
/* Added for Open SSH button with slightly darker color */
|
||||
.void-openssh-button {
|
||||
padding: 8px 20px;
|
||||
background-color: #656565; /* Slightly darker than the #5a5a5a in the TS file */
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
|
|
@ -35,43 +55,41 @@
|
|||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
.void-watermark-button:hover {
|
||||
background-color: #2563eb;
|
||||
.void-openssh-button:hover {
|
||||
background-color: #474747; /* Darker on hover */
|
||||
}
|
||||
.void-watermark-button:active {
|
||||
background-color: #2563eb;
|
||||
.void-openssh-button:active {
|
||||
background-color: #474747;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.void-settings-watermark-button {
|
||||
margin: 8px 0;
|
||||
padding: 8px 20px;
|
||||
background-color: var(--vscode-input-background);
|
||||
margin: 8px 0;
|
||||
padding: 8px 20px;
|
||||
background-color: var(--vscode-input-background);
|
||||
color: var(--vscode-input-foreground);
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
outline: none !important;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
outline: none !important;
|
||||
box-shadow: none !important;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.void-settings-watermark-button:hover {
|
||||
filter: brightness(1.1);
|
||||
}
|
||||
|
||||
.void-settings-watermark-button:active {
|
||||
filter: brightness(1.1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.void-link {
|
||||
color: #3b82f6;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.void-link:hover {
|
||||
opacity: 80%;
|
||||
}
|
||||
|
|
@ -86,7 +104,8 @@
|
|||
.void-scope,
|
||||
.void-scope * {
|
||||
scrollbar-width: thin !important;
|
||||
scrollbar-color: var(--void-bg-1) var(--void-bg-3) !important; /* For Firefox */
|
||||
scrollbar-color: var(--void-bg-1) var(--void-bg-3) !important;
|
||||
/* For Firefox */
|
||||
}
|
||||
|
||||
.void-scope::-webkit-scrollbar,
|
||||
|
|
@ -133,13 +152,16 @@
|
|||
background-color: var(--vscode-editor-background);
|
||||
--scrollbar-vertical-width: 14px;
|
||||
--scrollbar-horizontal-height: 6px;
|
||||
overflow: auto; /* Ensure scrollbars are shown when needed */
|
||||
overflow: auto;
|
||||
/* Ensure scrollbars are shown when needed */
|
||||
}
|
||||
|
||||
.void-scrollable-element,
|
||||
.void-scrollable-element * {
|
||||
scrollbar-width: thin !important; /* For Firefox */
|
||||
scrollbar-color: var(--void-bg-1) var(--void-bg-3) !important; /* For Firefox */
|
||||
scrollbar-width: thin !important;
|
||||
/* For Firefox */
|
||||
scrollbar-color: var(--void-bg-1) var(--void-bg-3) !important;
|
||||
/* For Firefox */
|
||||
}
|
||||
|
||||
.void-scrollable-element::-webkit-scrollbar,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import React, { Component, ErrorInfo, ReactNode } from 'react';
|
||||
import { ErrorDisplay } from './ErrorDisplay.js';
|
||||
import { WarningBox } from '../void-settings-tsx/WarningBox.js';
|
||||
|
||||
interface Props {
|
||||
children: ReactNode;
|
||||
|
|
@ -51,11 +52,12 @@ class ErrorBoundary extends Component<Props, State> {
|
|||
|
||||
// Use ErrorDisplay component as the default error UI
|
||||
return (
|
||||
<ErrorDisplay
|
||||
message={this.state.error + ''}
|
||||
fullError={this.state.error}
|
||||
onDismiss={this.props.onDismiss || null}
|
||||
/>
|
||||
<WarningBox text={this.state.error + ''} />
|
||||
// <ErrorDisplay
|
||||
// message={this.state.error + ''}
|
||||
// fullError={this.state.error}
|
||||
// onDismiss={this.props.onDismiss || null}
|
||||
// />
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import { acceptAllBg, acceptBorder, buttonFontSize, buttonTextColor, rejectAllBg
|
|||
import { ToolName, toolNames } from '../../../../common/prompt/prompts.js';
|
||||
import { RawToolCallObj } from '../../../../common/sendLLMMessageTypes.js';
|
||||
import { MAX_FILE_CHARS_PAGE } from '../../../toolsService.js';
|
||||
import ErrorBoundary from './ErrorBoundary.js';
|
||||
|
||||
|
||||
|
||||
|
|
@ -2483,7 +2484,7 @@ export const SidebarChat = () => {
|
|||
const currCheckpointIdx = chatThreadsState.allThreads[threadId]?.state?.currCheckpointIdx ?? undefined // if not exist, treat like checkpoint is last message (infinity)
|
||||
|
||||
const previousMessagesHTML = useMemo(() => {
|
||||
const lastMessageIdx = previousMessages.findLastIndex(v => v.role !== 'checkpoint')
|
||||
// const lastMessageIdx = previousMessages.findLastIndex(v => v.role !== 'checkpoint')
|
||||
// tool request shows up as Editing... if in progress
|
||||
return previousMessages.map((message, i) => {
|
||||
return <ChatBubble
|
||||
|
|
@ -2620,14 +2621,20 @@ export const SidebarChat = () => {
|
|||
<div ref={sidebarRef} className='w-full h-full flex flex-col overflow-hidden'>
|
||||
{/* History selector */}
|
||||
<div className={`w-full ${isHistoryOpen ? '' : 'hidden'} ring-2 ring-widget-shadow ring-inset z-10`}>
|
||||
<SidebarThreadSelector />
|
||||
<ErrorBoundary>
|
||||
<SidebarThreadSelector />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
|
||||
<div className='flex-1 flex flex-col overflow-hidden'>
|
||||
<div className={`flex-1 overflow-hidden ${previousMessages.length === 0 ? 'h-0 max-h-0 pb-2' : ''}`}>
|
||||
{messagesHTML}
|
||||
<ErrorBoundary>
|
||||
{messagesHTML}
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
{inputForm}
|
||||
<ErrorBoundary>
|
||||
{inputForm}
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,13 +3,14 @@
|
|||
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
|
||||
*--------------------------------------------------------------------------------------*/
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useAccessor, useIsDark, useSettingsState } from '../util/services.js';
|
||||
import { Brain, Check, DollarSign, ExternalLink, Lock, X } from 'lucide-react';
|
||||
import { Brain, Check, ChevronRight, DollarSign, ExternalLink, Lock, X } from 'lucide-react';
|
||||
import { displayInfoOfProviderName, ProviderName, providerNames, refreshableProviderNames } from '../../../../common/voidSettingsTypes.js';
|
||||
import { getModelCapabilities, ollamaRecommendedModels } from '../../../../common/modelCapabilities.js';
|
||||
import { ChatMarkdownRender } from '../markdown/ChatMarkdownRender.js';
|
||||
import { AddModelInputBox, AnimatedCheckmarkButton, ollamaSetupInstructions, OneClickSwitchButton, SettingsForProvider } from '../void-settings-tsx/Settings.js';
|
||||
import { ColorScheme } from '../../../../../../../platform/theme/common/theme.js';
|
||||
|
||||
const OVERRIDE_VALUE = false
|
||||
|
||||
|
|
@ -34,6 +35,30 @@ export const VoidOnboarding = () => {
|
|||
)
|
||||
}
|
||||
|
||||
const VoidIcon = () => {
|
||||
const accessor = useAccessor()
|
||||
const themeService = accessor.get('IThemeService')
|
||||
|
||||
const divRef = useRef<HTMLDivElement | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
// void icon style
|
||||
const updateTheme = () => {
|
||||
const theme = themeService.getColorTheme().type
|
||||
const isDark = theme === ColorScheme.DARK || theme === ColorScheme.HIGH_CONTRAST_DARK
|
||||
if (divRef.current) {
|
||||
divRef.current.style.maxWidth = '220px'
|
||||
divRef.current.style.opacity = '50%'
|
||||
divRef.current.style.filter = isDark ? '' : 'invert(1)' //brightness(.5)
|
||||
}
|
||||
}
|
||||
updateTheme()
|
||||
const d = themeService.onDidColorThemeChange(updateTheme)
|
||||
return () => d.dispose()
|
||||
}, [])
|
||||
|
||||
return <div ref={divRef} className='@@void-void-icon' />
|
||||
}
|
||||
|
||||
const FADE_DURATION_MS = 2000
|
||||
|
||||
|
|
@ -109,7 +134,7 @@ const NextButton = ({ onClick, ...props }: { onClick: () => void } & React.Butto
|
|||
className="px-6 py-2 bg-zinc-100 enabled:hover:bg-zinc-100 disabled:bg-zinc-100/40 disabled:cursor-not-allowed rounded text-black duration-600 transition-all"
|
||||
{...props.disabled && {
|
||||
'data-tooltip-id': 'void-tooltip',
|
||||
'data-tooltip-content': 'Disabled (Please enter all required fields or choose another provider)',
|
||||
'data-tooltip-content': 'Please enter all required fields or choose another provider',
|
||||
'data-tooltip-place': 'top',
|
||||
}}
|
||||
{...props}
|
||||
|
|
@ -144,7 +169,7 @@ const OnboardingPageShell = ({ top, bottom, content, hasMaxWidth = true, classNa
|
|||
<div className={`min-h-full text-lg flex flex-col gap-4 w-full mx-auto ${hasMaxWidth ? 'max-w-[600px]' : ''} ${className}`}>
|
||||
{top && <FadeIn className='w-full mb-auto pt-16'>{top}</FadeIn>}
|
||||
{content && <FadeIn className='w-full my-auto'>{content}</FadeIn>}
|
||||
{bottom && <div className='w-full mt-auto pb-8'>{bottom}</div>}
|
||||
{bottom && <div className='w-full pb-8'>{bottom}</div>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -157,7 +182,7 @@ const OllamaDownloadOrRemoveModelButton = ({ modelName, isModelInstalled, sizeGb
|
|||
href={`https://ollama.com/library/${modelName}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center text-void-fg-2 hover:text-void-fg-1"
|
||||
className="flex items-center justify-center text-void-fg-2 hover:text-void-fg-1"
|
||||
>
|
||||
<ExternalLink className="w-3.5 h-3.5" />
|
||||
</a>
|
||||
|
|
@ -353,7 +378,7 @@ const TableOfModelsForProvider = ({ providerName }: { providerName: ProviderName
|
|||
<td className="py-2 px-3"><YesNoText val={!!true} /></td>
|
||||
<td className="py-2 px-3"><YesNoText val={!!supportsFIM} /></td>
|
||||
{/* <td className="py-2 px-3"><YesNoText val={!!reasoningCapabilities} /></td> */}
|
||||
{isDetectableLocally && <td className="py-2 px-3">{!!isDownloaded ? <Check className="w-4 h-4" /> : <></>}</td>}
|
||||
{isDetectableLocally && <td className="py-2 px-3 flex items-center justify-center">{!!isDownloaded ? <Check className="w-4 h-4" /> : <></>}</td>}
|
||||
{providerName === 'ollama' && <th className="py-2 px-3">
|
||||
<OllamaDownloadOrRemoveModelButton modelName={modelName} isModelInstalled={infoOfModelName[modelName].isDownloaded} sizeGb={downloadable && downloadable.sizeGb} />
|
||||
</th>}
|
||||
|
|
@ -376,6 +401,57 @@ const TableOfModelsForProvider = ({ providerName }: { providerName: ProviderName
|
|||
|
||||
|
||||
|
||||
const PrimaryActionButton = ({ children, className, ringSize, ...props }: { children: React.ReactNode, ringSize?: undefined | 'xl' | 'screen' } & React.ButtonHTMLAttributes<HTMLButtonElement>) => {
|
||||
|
||||
|
||||
return (
|
||||
<button
|
||||
type='button'
|
||||
className={`
|
||||
flex items-center justify-center
|
||||
|
||||
text-white dark:text-black
|
||||
bg-black/90 dark:bg-white/90
|
||||
|
||||
${ringSize === 'xl' ? `
|
||||
gap-2 px-16 py-8
|
||||
hover:ring-8 active:ring-8
|
||||
transition-all duration-300 ease-in-out
|
||||
`
|
||||
: ringSize === 'screen' ? `
|
||||
gap-2 px-16 py-8
|
||||
ring-[3000px]
|
||||
transition-all duration-1000 ease-in-out
|
||||
`: ringSize === undefined ? `
|
||||
gap-1 px-4 py-2
|
||||
hover:ring-2 active:ring-2
|
||||
transition-all duration-300 ease-in-out
|
||||
`: ''}
|
||||
|
||||
hover:ring-black/90 dark:hover:ring-white/90
|
||||
active:ring-black/90 dark:active:ring-white/90
|
||||
|
||||
rounded-lg
|
||||
group
|
||||
${className}
|
||||
`}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<ChevronRight
|
||||
className={`
|
||||
transition-all duration-300 ease-in-out
|
||||
|
||||
transform
|
||||
group-hover:translate-x-1
|
||||
group-active:translate-x-1
|
||||
`}
|
||||
/>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
type WantToUseOption = 'smart' | 'private' | 'cheap' | 'all'
|
||||
|
||||
const VoidOnboardingContent = () => {
|
||||
|
|
@ -447,6 +523,19 @@ const VoidOnboardingContent = () => {
|
|||
</div>
|
||||
|
||||
|
||||
const lastPagePrevAndNextButtons = <div className="max-w-[600px] w-full mx-auto flex flex-col items-end">
|
||||
<div className="flex items-center gap-2">
|
||||
<PreviousButton
|
||||
onClick={() => { setPageIndex(pageIndex - 1) }}
|
||||
/>
|
||||
<PrimaryActionButton
|
||||
onClick={() => { voidSettingsService.setGlobalSetting('isOnboardingComplete', true); }}
|
||||
ringSize={voidSettingsState.globalSettings.isOnboardingComplete ? 'screen' : undefined}
|
||||
>Enter the Void</PrimaryActionButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
// cannot be md
|
||||
const basicDescOfWantToUseOption: { [wantToUseOption in WantToUseOption]: string } = {
|
||||
smart: "Models with the best performance on benchmarks.",
|
||||
|
|
@ -459,7 +548,7 @@ const VoidOnboardingContent = () => {
|
|||
const detailedDescOfWantToUseOption: { [wantToUseOption in WantToUseOption]: string } = {
|
||||
smart: "Most intelligent and best for agent mode.",
|
||||
private: "Private-hosted so your data never leaves your computer or network. [Email us](mailto:founders@voideditor.com) for help setting up at your company.",
|
||||
cheap: "Great deals like Gemini 2.5 Pro or self-host a model with Ollama or vLLM for free.",
|
||||
cheap: "Use great deals like Gemini 2.5 Pro, or self-host a model with Ollama or vLLM for free.",
|
||||
all: "",
|
||||
}
|
||||
|
||||
|
|
@ -490,17 +579,26 @@ const VoidOnboardingContent = () => {
|
|||
const contentOfIdx: { [pageIndex: number]: React.ReactNode } = {
|
||||
0: <OnboardingPageShell
|
||||
content={
|
||||
<>
|
||||
<div className='flex flex-col items-center gap-8'>
|
||||
<div className="text-5xl font-light text-center">Welcome to Void</div>
|
||||
|
||||
{/* Slice of Void image */}
|
||||
<div className='max-w-md w-full h-[30vh] mx-auto flex items-center justify-center'>
|
||||
<VoidIcon />
|
||||
</div>
|
||||
|
||||
|
||||
<FadeIn
|
||||
delayMs={1500}
|
||||
className="text-center"
|
||||
onClick={() => { setPageIndex(pageIndex + 1) }}
|
||||
delayMs={1000}
|
||||
>
|
||||
Get Started
|
||||
<PrimaryActionButton
|
||||
onClick={() => { setPageIndex(pageIndex + 1) }}
|
||||
>
|
||||
Get Started
|
||||
</PrimaryActionButton>
|
||||
</FadeIn>
|
||||
|
||||
</>
|
||||
</div>
|
||||
}
|
||||
/>,
|
||||
1: <OnboardingPageShell
|
||||
|
|
@ -516,7 +614,7 @@ const VoidOnboardingContent = () => {
|
|||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 w-full max-w-[800px] mx-auto mt-8">
|
||||
<button
|
||||
onClick={() => { setWantToUseOption('smart'); setPageIndex(pageIndex + 1); }}
|
||||
className="flex flex-col p-6 rounded bg-void-bg-2 border border-void-border-3 hover:border-void-border-1 transition-colors focus:outline-none focus:border-void-accent-border relative overflow-hidden min-h-[160px]"
|
||||
className="flex flex-col p-6 rounded bg-void-bg-2 border border-void-border-3 hover:brightness-110 transition-colors focus:outline-none focus:border-void-accent-border relative overflow-hidden min-h-[160px]"
|
||||
>
|
||||
<div className="flex items-center mb-3">
|
||||
<Brain size={24} className="text-void-fg-2 mr-2" />
|
||||
|
|
@ -527,7 +625,7 @@ const VoidOnboardingContent = () => {
|
|||
|
||||
<button
|
||||
onClick={() => { setWantToUseOption('private'); setPageIndex(pageIndex + 1); }}
|
||||
className="flex flex-col p-6 rounded bg-void-bg-2 border border-void-border-3 hover:border-void-border-1 transition-colors focus:outline-none focus:border-void-accent-border relative overflow-hidden min-h-[160px]"
|
||||
className="flex flex-col p-6 rounded bg-void-bg-2 border border-void-border-3 hover:brightness-110 transition-colors focus:outline-none focus:border-void-accent-border relative overflow-hidden min-h-[160px]"
|
||||
>
|
||||
<div className="flex items-center mb-3">
|
||||
<Lock size={24} className="text-void-fg-2 mr-2" />
|
||||
|
|
@ -538,7 +636,7 @@ const VoidOnboardingContent = () => {
|
|||
|
||||
<button
|
||||
onClick={() => { setWantToUseOption('cheap'); setPageIndex(pageIndex + 1); }}
|
||||
className="flex flex-col p-6 rounded bg-void-bg-2 border border-void-border-3 hover:border-void-border-1 transition-colors focus:outline-none focus:border-void-accent-border relative overflow-hidden min-h-[160px]"
|
||||
className="flex flex-col p-6 rounded bg-void-bg-2 border border-void-border-3 hover:brightness-110 transition-colors focus:outline-none focus:border-void-accent-border relative overflow-hidden min-h-[160px]"
|
||||
>
|
||||
<div className="flex items-center mb-3">
|
||||
<DollarSign size={24} className="text-void-fg-2 mr-2" />
|
||||
|
|
@ -550,6 +648,11 @@ const VoidOnboardingContent = () => {
|
|||
|
||||
|
||||
</div>}
|
||||
bottom={
|
||||
<div className='mx-auto w-full max-w-[800px]'>
|
||||
<PreviousButton onClick={() => { setPageIndex(pageIndex - 1) }} />
|
||||
</div>
|
||||
}
|
||||
/>,
|
||||
2: <OnboardingPageShell
|
||||
top={
|
||||
|
|
@ -665,7 +768,7 @@ const VoidOnboardingContent = () => {
|
|||
|
||||
|
||||
{/* ModelsTable and ProviderFields */}
|
||||
{selectedProviderName && <div className='mt-4'>
|
||||
{selectedProviderName && <div className='mt-4 w-fit mx-auto'>
|
||||
|
||||
|
||||
{/* Models Table */}
|
||||
|
|
@ -673,12 +776,13 @@ const VoidOnboardingContent = () => {
|
|||
|
||||
|
||||
{/* Add provider section - simplified styling */}
|
||||
<div className='mb-5 mt-8'>
|
||||
<div className='mb-5 mt-8 mx-auto'>
|
||||
<div className=''>
|
||||
Add {displayInfoOfProviderName(selectedProviderName).title}
|
||||
|
||||
|
||||
{selectedProviderName === 'ollama' ? ollamaSetupInstructions : ''}
|
||||
<div className='my-4'>
|
||||
{selectedProviderName === 'ollama' ? ollamaSetupInstructions : ''}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -733,35 +837,33 @@ const VoidOnboardingContent = () => {
|
|||
</div>
|
||||
</div>
|
||||
}
|
||||
bottom={prevAndNextButtons}
|
||||
/>,
|
||||
4: <OnboardingPageShell
|
||||
|
||||
content={
|
||||
<>
|
||||
<div className="text-5xl font-light text-center">Jump in</div>
|
||||
<div
|
||||
className="text-center"
|
||||
onClick={() => {
|
||||
// TODO make a fadeout effect
|
||||
voidSettingsService.setGlobalSetting('isOnboardingComplete', true)
|
||||
}}
|
||||
|
||||
>
|
||||
Enter the Void
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
bottom={
|
||||
<PreviousButton
|
||||
onClick={() => { setPageIndex(pageIndex - 1) }}
|
||||
/>
|
||||
}
|
||||
bottom={lastPagePrevAndNextButtons}
|
||||
// bottom={prevAndNextButtons}
|
||||
/>,
|
||||
// 4: <OnboardingPageShell
|
||||
// content={
|
||||
// <>
|
||||
// <div
|
||||
// className='flex justify-center'
|
||||
// >
|
||||
// <PrimaryActionButton
|
||||
// onClick={() => { voidSettingsService.setGlobalSetting('isOnboardingComplete', true); }}
|
||||
// ringSize={voidSettingsState.globalSettings.isOnboardingComplete ? 'screen' : undefined}
|
||||
// className='text-4xl'
|
||||
// >Enter the Void</PrimaryActionButton>
|
||||
// </div>
|
||||
// </>
|
||||
// }
|
||||
// bottom={
|
||||
// <PreviousButton
|
||||
// onClick={() => { setPageIndex(pageIndex - 1) }}
|
||||
// />
|
||||
// }
|
||||
// />,
|
||||
}
|
||||
|
||||
|
||||
return <div key={pageIndex} className="w-full h-full text-left mx-auto overflow-y-auto flex flex-col items-center justify-around">
|
||||
return <div key={pageIndex} className="w-full h-full text-left mx-auto overflow-y-scroll flex flex-col items-center justify-around">
|
||||
{contentOfIdx[pageIndex]}
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import { IconWarning } from '../sidebar-tsx/SidebarChat.js'
|
|||
import { VOID_OPEN_SETTINGS_ACTION_ID, VOID_TOGGLE_SETTINGS_ACTION_ID } from '../../../voidSettingsPane.js'
|
||||
import { modelFilterOfFeatureName, ModelOption } from '../../../../../../../workbench/contrib/void/common/voidSettingsService.js'
|
||||
import { WarningBox } from './WarningBox.js'
|
||||
import ErrorBoundary from '../sidebar-tsx/ErrorBoundary.js'
|
||||
|
||||
const optionsEqual = (m1: ModelOption[], m2: ModelOption[]) => {
|
||||
if (m1.length !== m2.length) return false
|
||||
|
|
@ -92,5 +93,7 @@ export const ModelDropdown = ({ featureName, className }: { featureName: Feature
|
|||
: 'Provider required'
|
||||
} />
|
||||
|
||||
return <MemoizedModelDropdown featureName={featureName} className={className} />
|
||||
return <ErrorBoundary>
|
||||
<MemoizedModelDropdown featureName={featureName} className={className} />
|
||||
</ErrorBoundary>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -572,182 +572,6 @@ const RedoOnboardingButton = ({ className }: { className?: string }) => {
|
|||
}
|
||||
|
||||
|
||||
|
||||
export const FeaturesTab = () => {
|
||||
const voidSettingsState = useSettingsState()
|
||||
const accessor = useAccessor()
|
||||
const voidSettingsService = accessor.get('IVoidSettingsService')
|
||||
|
||||
|
||||
return <>
|
||||
<h2 className={`text-3xl mb-2`}>Models</h2>
|
||||
<ErrorBoundary>
|
||||
<ModelDump />
|
||||
<AddModelInputBox className='mt-4' compact />
|
||||
<RedoOnboardingButton className='mt-2 mb-4' />
|
||||
<AutoDetectLocalModelsToggle />
|
||||
<RefreshableModels />
|
||||
</ErrorBoundary>
|
||||
|
||||
|
||||
<h2 className={`text-3xl mb-2 mt-12`}>Local Providers</h2>
|
||||
{/* <h3 className={`opacity-50 mb-2`}>{`Keep your data private by hosting AI locally on your computer.`}</h3> */}
|
||||
{/* <h3 className={`opacity-50 mb-2`}>{`Instructions:`}</h3> */}
|
||||
{/* <h3 className={`mb-2`}>{`Void can access any model that you host locally. We automatically detect your local models by default.`}</h3> */}
|
||||
<h3 className={`text-void-fg-3 mb-2`}>{`Void can access any model that you host locally. We automatically detect your local models by default.`}</h3>
|
||||
|
||||
<div className='opacity-80 mb-4'>
|
||||
{ollamaSetupInstructions}
|
||||
</div>
|
||||
|
||||
<ErrorBoundary>
|
||||
<VoidProviderSettings providerNames={localProviderNames} />
|
||||
</ErrorBoundary>
|
||||
|
||||
<h2 className={`text-3xl mb-2 mt-12`}>Providers</h2>
|
||||
<h3 className={`text-void-fg-3 mb-2`}>{`Void can access models from Anthropic, OpenAI, OpenRouter, and more.`}</h3>
|
||||
{/* <h3 className={`opacity-50 mb-2`}>{`Access models like ChatGPT and Claude. We recommend using Anthropic or OpenAI as providers, or Groq as a faster alternative.`}</h3> */}
|
||||
<ErrorBoundary>
|
||||
<VoidProviderSettings providerNames={nonlocalProviderNames} />
|
||||
</ErrorBoundary>
|
||||
|
||||
|
||||
|
||||
<h2 className={`text-3xl mt-12`}>Feature Options</h2>
|
||||
<ErrorBoundary>
|
||||
{/* L1 */}
|
||||
<div className='flex items-start justify-around mt-4 my-4 gap-x-8'>
|
||||
{/* FIM */}
|
||||
<div className='w-full'>
|
||||
<h4 className={`text-base`}>{displayInfoOfFeatureName('Autocomplete')}</h4>
|
||||
<div className='text-sm italic text-void-fg-3 mt-1 mb-4'>
|
||||
<span>
|
||||
Experimental.{' '}
|
||||
</span>
|
||||
<span
|
||||
className='hover:brightness-110'
|
||||
data-tooltip-id='void-tooltip'
|
||||
data-tooltip-content='We recommend using qwen2.5-coder:1.5b with Ollama.'
|
||||
data-tooltip-class-name='void-max-w-[20px]'
|
||||
>
|
||||
Only works with FIM models.*
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className='my-2'>
|
||||
{/* Enable Switch */}
|
||||
<div className='flex items-center gap-x-2 my-2'>
|
||||
<VoidSwitch
|
||||
size='xs'
|
||||
value={voidSettingsState.globalSettings.enableAutocomplete}
|
||||
onChange={(newVal) => voidSettingsService.setGlobalSetting('enableAutocomplete', newVal)}
|
||||
/>
|
||||
<span className='text-void-fg-3 text-xs pointer-events-none'>{voidSettingsState.globalSettings.enableAutocomplete ? 'Enabled' : 'Disabled'}</span>
|
||||
</div>
|
||||
{/* Model Dropdown */}
|
||||
<div className={`my-2 ${!voidSettingsState.globalSettings.enableAutocomplete ? 'hidden' : ''}`}>
|
||||
<ModelDropdown featureName={'Autocomplete'} className='text-xs text-void-fg-3 bg-void-bg-1 border border-void-border-1 rounded p-0.5 px-1' />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* Apply */}
|
||||
<div className='w-full'>
|
||||
<h4 className={`text-base`}>{displayInfoOfFeatureName('Apply')}</h4>
|
||||
<div className='text-sm italic text-void-fg-3 mt-1 mb-4'>Settings that control the behavior of the Apply button and the Edit tool.</div>
|
||||
|
||||
<div className='my-2'>
|
||||
{/* Sync to Chat Switch */}
|
||||
<div className='flex items-center gap-x-2 my-2'>
|
||||
<VoidSwitch
|
||||
size='xs'
|
||||
value={voidSettingsState.globalSettings.syncApplyToChat}
|
||||
onChange={(newVal) => voidSettingsService.setGlobalSetting('syncApplyToChat', newVal)}
|
||||
/>
|
||||
<span className='text-void-fg-3 text-xs pointer-events-none'>{voidSettingsState.globalSettings.syncApplyToChat ? 'Same as Chat model' : 'Different model'}</span>
|
||||
</div>
|
||||
|
||||
{/* Model Dropdown */}
|
||||
<div className={`my-2 ${voidSettingsState.globalSettings.syncApplyToChat ? 'hidden' : ''}`}>
|
||||
<ModelDropdown featureName={'Apply'} className='text-xs text-void-fg-3 bg-void-bg-1 border border-void-border-1 rounded p-0.5 px-1' />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div className='my-2'>
|
||||
{/* Fast Apply Method Dropdown */}
|
||||
<div className='flex items-center gap-x-2 my-2'>
|
||||
<FastApplyMethodDropdown />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* L2 */}
|
||||
<div className='flex items-start justify-around my-4 gap-x-8'>
|
||||
|
||||
{/* Tools Section */}
|
||||
<div className='w-full'>
|
||||
<h4 className={`text-base`}>Tools</h4>
|
||||
<div className='text-sm italic text-void-fg-3 mt-1 mb-4'>{`Tools are functions that LLMs can call. Some tools require user approval.`}</div>
|
||||
|
||||
<div className='my-2'>
|
||||
{/* Auto Accept Switch */}
|
||||
<div className='flex items-center gap-x-2 my-2'>
|
||||
<VoidSwitch
|
||||
size='xs'
|
||||
value={voidSettingsState.globalSettings.autoApprove}
|
||||
onChange={(newVal) => voidSettingsService.setGlobalSetting('autoApprove', newVal)}
|
||||
/>
|
||||
<span className='text-void-fg-3 text-xs pointer-events-none'>{voidSettingsState.globalSettings.autoApprove ? 'Auto-approve' : 'Auto-approve'}</span>
|
||||
</div>
|
||||
|
||||
{/* Tool Lint Errors Switch */}
|
||||
<div className='flex items-center gap-x-2 my-2'>
|
||||
<VoidSwitch
|
||||
size='xs'
|
||||
value={voidSettingsState.globalSettings.includeToolLintErrors}
|
||||
onChange={(newVal) => voidSettingsService.setGlobalSetting('includeToolLintErrors', newVal)}
|
||||
/>
|
||||
<span className='text-void-fg-3 text-xs pointer-events-none'>{voidSettingsState.globalSettings.includeToolLintErrors ? 'Fix lint errors' : `Fix lint errors`}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div className='w-full'>
|
||||
<h4 className={`text-base`}>Editor</h4>
|
||||
<div className='text-sm italic text-void-fg-3 mt-1 mb-4'>{`Settings that control the visibility of suggestions and widgets in the code editor.`}</div>
|
||||
|
||||
<div className='my-2'>
|
||||
{/* Auto Accept Switch */}
|
||||
<div className='flex items-center gap-x-2 my-2'>
|
||||
<VoidSwitch
|
||||
size='xs'
|
||||
value={voidSettingsState.globalSettings.showInlineSuggestions}
|
||||
onChange={(newVal) => voidSettingsService.setGlobalSetting('showInlineSuggestions', newVal)}
|
||||
/>
|
||||
<span className='text-void-fg-3 text-xs pointer-events-none'>{voidSettingsState.globalSettings.showInlineSuggestions ? 'Show suggestions on select' : 'Show suggestions on select'}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div className='py-8' />
|
||||
|
||||
</ErrorBoundary>
|
||||
|
||||
</>
|
||||
}
|
||||
|
||||
|
||||
type TransferEditorType = 'VS Code' | 'Cursor' | 'Windsurf'
|
||||
// https://github.com/VSCodium/vscodium/blob/master/docs/index.md#migrating-from-visual-studio-code-to-vscodium
|
||||
// https://code.visualstudio.com/docs/editor/extension-marketplace#_where-are-extensions-installed
|
||||
|
|
@ -954,113 +778,264 @@ export const OneClickSwitchButton = ({ fromEditor = 'VS Code', className = '' }:
|
|||
}
|
||||
|
||||
|
||||
const GeneralTab = () => {
|
||||
const accessor = useAccessor()
|
||||
const commandService = accessor.get('ICommandService')
|
||||
const environmentService = accessor.get('IEnvironmentService')
|
||||
const nativeHostService = accessor.get('INativeHostService')
|
||||
|
||||
return <>
|
||||
<div className=''>
|
||||
<h2 className={`text-3xl mb-2`}>One-Click Switch</h2>
|
||||
<h4 className={`text-void-fg-3 mb-4`}>{`Transfer your settings from another editor to Void in one click.`}</h4>
|
||||
|
||||
<div className='flex flex-col gap-4'>
|
||||
<OneClickSwitchButton className='w-48' fromEditor="VS Code" />
|
||||
<OneClickSwitchButton className='w-48' fromEditor="Cursor" />
|
||||
<OneClickSwitchButton className='w-48' fromEditor="Windsurf" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div className='mt-12'>
|
||||
<h2 className={`text-3xl mb-2`}>Built-in Settings</h2>
|
||||
<h4 className={`text-void-fg-3 mb-4`}>{`IDE settings, keyboard settings, and theme customization.`}</h4>
|
||||
|
||||
<div className='my-4'>
|
||||
<VoidButtonBgDarken className='px-4 py-2' onClick={() => { commandService.executeCommand('workbench.action.openSettings') }}>
|
||||
General Settings
|
||||
</VoidButtonBgDarken>
|
||||
</div>
|
||||
<div className='my-4'>
|
||||
<VoidButtonBgDarken className='px-4 py-2' onClick={() => { commandService.executeCommand('workbench.action.openGlobalKeybindings') }}>
|
||||
Keyboard Settings
|
||||
</VoidButtonBgDarken>
|
||||
</div>
|
||||
<div className='my-4'>
|
||||
<VoidButtonBgDarken className='px-4 py-2' onClick={() => { commandService.executeCommand('workbench.action.selectTheme') }}>
|
||||
Theme Settings
|
||||
</VoidButtonBgDarken>
|
||||
</div>
|
||||
<div className='my-4'>
|
||||
<VoidButtonBgDarken className='px-4 py-2' onClick={() => { nativeHostService.showItemInFolder(environmentService.logsHome.fsPath) }}>
|
||||
Open Logs
|
||||
</VoidButtonBgDarken>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div className='mt-12 max-w-[600px]'>
|
||||
<h2 className={`text-3xl mb-2`}>AI Instructions</h2>
|
||||
<h4 className={`text-void-fg-3 mb-4`}>{`Instructions to include on all AI requests.`}</h4>
|
||||
<AIInstructionsBox />
|
||||
</div>
|
||||
|
||||
|
||||
</>
|
||||
}
|
||||
|
||||
// full settings
|
||||
|
||||
export const Settings = () => {
|
||||
const isDark = useIsDark()
|
||||
|
||||
const [tab, setTab] = useState<TabName>('models')
|
||||
const accessor = useAccessor()
|
||||
const commandService = accessor.get('ICommandService')
|
||||
const environmentService = accessor.get('IEnvironmentService')
|
||||
const nativeHostService = accessor.get('INativeHostService')
|
||||
const settingsState = useSettingsState()
|
||||
const voidSettingsService = accessor.get('IVoidSettingsService')
|
||||
|
||||
return <div className={`@@void-scope ${isDark ? 'dark' : ''}`} style={{ height: '100%', width: '100%' }}>
|
||||
<div className='overflow-y-auto w-full h-full px-10 py-10 select-none'>
|
||||
|
||||
<div className='max-w-5xl mx-auto'>
|
||||
<div className='max-w-xl mx-auto'>
|
||||
|
||||
<h1 className='text-2xl w-full'>{`Void's Settings`}</h1>
|
||||
|
||||
{/* separator */}
|
||||
<div className='w-full h-[1px] my-4' />
|
||||
|
||||
<div className='flex items-stretch'>
|
||||
{/* Models section (formerly FeaturesTab) */}
|
||||
<ErrorBoundary>
|
||||
<h2 className={`text-3xl mb-2`}>Models</h2>
|
||||
<ModelDump />
|
||||
<AddModelInputBox className='mt-4' compact />
|
||||
<RedoOnboardingButton className='mt-2 mb-4' />
|
||||
<AutoDetectLocalModelsToggle />
|
||||
<RefreshableModels />
|
||||
</ErrorBoundary>
|
||||
|
||||
{/* tabs */}
|
||||
<div className='flex flex-col w-full max-w-32'>
|
||||
<button className={`text-left p-1 px-3 my-0.5 rounded-sm overflow-hidden ${tab === 'models' ? 'bg-black/10 dark:bg-gray-200/10' : ''} hover:bg-black/10 hover:dark:bg-gray-200/10 active:bg-black/10 active:dark:bg-gray-200/10 `}
|
||||
onClick={() => { setTab('models') }}
|
||||
>Models</button>
|
||||
<button className={`text-left p-1 px-3 my-0.5 rounded-sm overflow-hidden ${tab === 'general' ? 'bg-black/10 dark:bg-gray-200/10' : ''} hover:bg-black/10 hover:dark:bg-gray-200/10 active:bg-black/10 active:dark:bg-gray-200/10 `}
|
||||
onClick={() => { setTab('general') }}
|
||||
>General</button>
|
||||
|
||||
<h2 className={`text-3xl mb-2 mt-12`}>Local Providers</h2>
|
||||
<h3 className={`text-void-fg-3 mb-2`}>{`Void can access any model that you host locally. We automatically detect your local models by default.`}</h3>
|
||||
|
||||
<div className='opacity-80 mb-4'>
|
||||
{ollamaSetupInstructions}
|
||||
</div>
|
||||
|
||||
<ErrorBoundary>
|
||||
<VoidProviderSettings providerNames={localProviderNames} />
|
||||
</ErrorBoundary>
|
||||
|
||||
<h2 className={`text-3xl mb-2 mt-12`}>Providers</h2>
|
||||
<h3 className={`text-void-fg-3 mb-2`}>{`Void can access models from Anthropic, OpenAI, OpenRouter, and more.`}</h3>
|
||||
<ErrorBoundary>
|
||||
<VoidProviderSettings providerNames={nonlocalProviderNames} />
|
||||
</ErrorBoundary>
|
||||
|
||||
|
||||
|
||||
<h2 className={`text-3xl mt-12`}>Feature Options</h2>
|
||||
{/* L1 */}
|
||||
|
||||
<div className='flex items-start justify-around my-4 gap-x-8'>
|
||||
<ErrorBoundary>
|
||||
{/* FIM */}
|
||||
<div className='w-full'>
|
||||
<h4 className={`text-base`}>{displayInfoOfFeatureName('Autocomplete')}</h4>
|
||||
<div className='text-sm italic text-void-fg-3 mt-1 mb-4'>
|
||||
<span>
|
||||
Experimental.{' '}
|
||||
</span>
|
||||
<span
|
||||
className='hover:brightness-110'
|
||||
data-tooltip-id='void-tooltip'
|
||||
data-tooltip-content='We recommend using qwen2.5-coder:1.5b with Ollama.'
|
||||
data-tooltip-class-name='void-max-w-[20px]'
|
||||
>
|
||||
Only works with FIM models.*
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className='my-2'>
|
||||
{/* Enable Switch */}
|
||||
<ErrorBoundary>
|
||||
<div className='flex items-center gap-x-2 my-2'>
|
||||
<VoidSwitch
|
||||
size='xs'
|
||||
value={settingsState.globalSettings.enableAutocomplete}
|
||||
onChange={(newVal) => voidSettingsService.setGlobalSetting('enableAutocomplete', newVal)}
|
||||
/>
|
||||
<span className='text-void-fg-3 text-xs pointer-events-none'>{settingsState.globalSettings.enableAutocomplete ? 'Enabled' : 'Disabled'}</span>
|
||||
</div>
|
||||
</ErrorBoundary>
|
||||
|
||||
{/* Model Dropdown */}
|
||||
<ErrorBoundary>
|
||||
<div className={`my-2 ${!settingsState.globalSettings.enableAutocomplete ? 'hidden' : ''}`}>
|
||||
<ModelDropdown featureName={'Autocomplete'} className='text-xs text-void-fg-3 bg-void-bg-1 border border-void-border-1 rounded p-0.5 px-1' />
|
||||
</div>
|
||||
</ErrorBoundary>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</ErrorBoundary>
|
||||
|
||||
{/* Apply */}
|
||||
<ErrorBoundary>
|
||||
|
||||
<div className='w-full'>
|
||||
<h4 className={`text-base`}>{displayInfoOfFeatureName('Apply')}</h4>
|
||||
<div className='text-sm italic text-void-fg-3 mt-1 mb-4'>Settings that control the behavior of the Apply button and the Edit tool.</div>
|
||||
|
||||
<div className='my-2'>
|
||||
{/* Sync to Chat Switch */}
|
||||
<div className='flex items-center gap-x-2 my-2'>
|
||||
<VoidSwitch
|
||||
size='xs'
|
||||
value={settingsState.globalSettings.syncApplyToChat}
|
||||
onChange={(newVal) => voidSettingsService.setGlobalSetting('syncApplyToChat', newVal)}
|
||||
/>
|
||||
<span className='text-void-fg-3 text-xs pointer-events-none'>{settingsState.globalSettings.syncApplyToChat ? 'Same as Chat model' : 'Different model'}</span>
|
||||
</div>
|
||||
|
||||
{/* Model Dropdown */}
|
||||
<div className={`my-2 ${settingsState.globalSettings.syncApplyToChat ? 'hidden' : ''}`}>
|
||||
<ModelDropdown featureName={'Apply'} className='text-xs text-void-fg-3 bg-void-bg-1 border border-void-border-1 rounded p-0.5 px-1' />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div className='my-2'>
|
||||
{/* Fast Apply Method Dropdown */}
|
||||
<div className='flex items-center gap-x-2 my-2'>
|
||||
<FastApplyMethodDropdown />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</ErrorBoundary>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{/* L2 */}
|
||||
|
||||
<div className='flex items-start justify-around my-4 gap-x-8'>
|
||||
|
||||
{/* Tools Section */}
|
||||
<div className='w-full'>
|
||||
<h4 className={`text-base`}>Tools</h4>
|
||||
<div className='text-sm italic text-void-fg-3 mt-1 mb-4'>{`Tools are functions that LLMs can call. Some tools require user approval.`}</div>
|
||||
|
||||
<div className='my-2'>
|
||||
{/* Auto Accept Switch */}
|
||||
<ErrorBoundary>
|
||||
|
||||
<div className='flex items-center gap-x-2 my-2'>
|
||||
<VoidSwitch
|
||||
size='xs'
|
||||
value={settingsState.globalSettings.autoApprove}
|
||||
onChange={(newVal) => voidSettingsService.setGlobalSetting('autoApprove', newVal)}
|
||||
/>
|
||||
<span className='text-void-fg-3 text-xs pointer-events-none'>{settingsState.globalSettings.autoApprove ? 'Auto-approve' : 'Auto-approve'}</span>
|
||||
</div>
|
||||
</ErrorBoundary>
|
||||
|
||||
{/* Tool Lint Errors Switch */}
|
||||
<ErrorBoundary>
|
||||
|
||||
<div className='flex items-center gap-x-2 my-2'>
|
||||
<VoidSwitch
|
||||
size='xs'
|
||||
value={settingsState.globalSettings.includeToolLintErrors}
|
||||
onChange={(newVal) => voidSettingsService.setGlobalSetting('includeToolLintErrors', newVal)}
|
||||
/>
|
||||
<span className='text-void-fg-3 text-xs pointer-events-none'>{settingsState.globalSettings.includeToolLintErrors ? 'Fix lint errors' : `Fix lint errors`}</span>
|
||||
</div>
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* separator */}
|
||||
<div className='w-[1px] mx-4' />
|
||||
|
||||
|
||||
{/* content */}
|
||||
<div className='w-full min-w-[550px]'>
|
||||
<div className='w-full'>
|
||||
<h4 className={`text-base`}>Editor</h4>
|
||||
<div className='text-sm italic text-void-fg-3 mt-1 mb-4'>{`Settings that control the visibility of suggestions and widgets in the code editor.`}</div>
|
||||
|
||||
<div className={`${tab !== 'models' ? 'hidden' : ''}`}>
|
||||
<FeaturesTab />
|
||||
<div className='my-2'>
|
||||
{/* Auto Accept Switch */}
|
||||
<ErrorBoundary>
|
||||
<div className='flex items-center gap-x-2 my-2'>
|
||||
<VoidSwitch
|
||||
size='xs'
|
||||
value={settingsState.globalSettings.showInlineSuggestions}
|
||||
onChange={(newVal) => voidSettingsService.setGlobalSetting('showInlineSuggestions', newVal)}
|
||||
/>
|
||||
<span className='text-void-fg-3 text-xs pointer-events-none'>{settingsState.globalSettings.showInlineSuggestions ? 'Show suggestions on select' : 'Show suggestions on select'}</span>
|
||||
</div>
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
|
||||
<div className={`${tab !== 'general' ? 'hidden' : ''}`}>
|
||||
<GeneralTab />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{/* General section (formerly GeneralTab) */}
|
||||
<div className='mt-12'>
|
||||
<ErrorBoundary>
|
||||
<h2 className={`text-3xl mb-2 mt-12`}>One-Click Switch</h2>
|
||||
<h4 className={`text-void-fg-3 mb-4`}>{`Transfer your settings from another editor to Void in one click.`}</h4>
|
||||
|
||||
<div className='flex flex-col gap-4'>
|
||||
<OneClickSwitchButton className='w-48' fromEditor="VS Code" />
|
||||
<OneClickSwitchButton className='w-48' fromEditor="Cursor" />
|
||||
<OneClickSwitchButton className='w-48' fromEditor="Windsurf" />
|
||||
</div>
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div className='mt-12'>
|
||||
|
||||
<h2 className={`text-3xl mb-2`}>Built-in Settings</h2>
|
||||
<h4 className={`text-void-fg-3 mb-4`}>{`IDE settings, keyboard settings, and theme customization.`}</h4>
|
||||
|
||||
<ErrorBoundary>
|
||||
<div className='my-4'>
|
||||
<VoidButtonBgDarken className='px-4 py-2' onClick={() => { commandService.executeCommand('workbench.action.openSettings') }}>
|
||||
General Settings
|
||||
</VoidButtonBgDarken>
|
||||
</div>
|
||||
<div className='my-4'>
|
||||
<VoidButtonBgDarken className='px-4 py-2' onClick={() => { commandService.executeCommand('workbench.action.openGlobalKeybindings') }}>
|
||||
Keyboard Settings
|
||||
</VoidButtonBgDarken>
|
||||
</div>
|
||||
<div className='my-4'>
|
||||
<VoidButtonBgDarken className='px-4 py-2' onClick={() => { commandService.executeCommand('workbench.action.selectTheme') }}>
|
||||
Theme Settings
|
||||
</VoidButtonBgDarken>
|
||||
</div>
|
||||
<div className='my-4'>
|
||||
<VoidButtonBgDarken className='px-4 py-2' onClick={() => { nativeHostService.showItemInFolder(environmentService.logsHome.fsPath) }}>
|
||||
Open Logs
|
||||
</VoidButtonBgDarken>
|
||||
</div>
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
|
||||
|
||||
<div className='mt-12 max-w-[600px]'>
|
||||
<h2 className={`text-3xl mb-2`}>AI Instructions</h2>
|
||||
<h4 className={`text-void-fg-3 mb-4`}>
|
||||
<ChatMarkdownRender inPTag={true} string={`
|
||||
System instructions to include with all AI requests.
|
||||
Alternatively, place a \`.voidinstructions\` file in the root of your workspace.
|
||||
`} chatMessageLocation={undefined} />
|
||||
</h4>
|
||||
<ErrorBoundary>
|
||||
<AIInstructionsBox />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -102,8 +102,7 @@ export const VoidTooltip = () => {
|
|||
id="void-tooltip-ollama-settings"
|
||||
border='1px solid rgba(100,100,100,.2)'
|
||||
opacity={1}
|
||||
openOnClick
|
||||
openEvents={{ mouseover: true }}
|
||||
openEvents={{ mouseover: true, click: true, focus: true }}
|
||||
place='right'
|
||||
style={{ pointerEvents: 'all', userSelect: 'text', fontSize: 11 }}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import './media/void.css'
|
|||
// update (frontend part, also see platform/)
|
||||
import './voidUpdateActions.js'
|
||||
|
||||
import './convertToLLMMessageWorkbenchContrib.js'
|
||||
|
||||
// tools
|
||||
import './toolsService.js'
|
||||
|
|
|
|||
|
|
@ -362,8 +362,6 @@ export class VoidCommandBarService extends Disposable implements IVoidCommandBar
|
|||
|
||||
registerSingleton(IVoidCommandBarService, VoidCommandBarService, InstantiationType.Delayed); // delayed is needed here :(
|
||||
|
||||
// registerWorkbenchContribution2(VoidCommandBarService.ID, VoidCommandBarService, WorkbenchPhase.BlockRestore);
|
||||
|
||||
|
||||
export type VoidCommandBarProps = {
|
||||
uri: URI | null;
|
||||
|
|
|
|||
|
|
@ -783,7 +783,7 @@ const groqSettings: VoidStaticProviderInfo = {
|
|||
}
|
||||
|
||||
const ollamaModelOptions = {
|
||||
'qwen2.5-coder:3b': {
|
||||
'qwen2.5-coder:1.5b': {
|
||||
contextWindow: 32_000,
|
||||
maxOutputTokens: null,
|
||||
cost: { input: 0, output: 0 },
|
||||
|
|
@ -792,6 +792,15 @@ const ollamaModelOptions = {
|
|||
supportsSystemMessage: 'system-role',
|
||||
reasoningCapabilities: false,
|
||||
},
|
||||
'llama3.1': {
|
||||
contextWindow: 128_000,
|
||||
maxOutputTokens: null,
|
||||
cost: { input: 0, output: 0 },
|
||||
downloadable: { sizeGb: 4.9 },
|
||||
supportsFIM: false,
|
||||
supportsSystemMessage: 'system-role',
|
||||
reasoningCapabilities: false,
|
||||
},
|
||||
'qwen2.5-coder': {
|
||||
contextWindow: 128_000,
|
||||
maxOutputTokens: null,
|
||||
|
|
@ -822,7 +831,7 @@ const ollamaModelOptions = {
|
|||
|
||||
} as const satisfies Record<string, VoidStaticModelInfo>
|
||||
|
||||
export const ollamaRecommendedModels = ['qwen2.5-coder:3b', 'qwq', 'deepseek-r1'] as const satisfies (keyof typeof ollamaModelOptions)[]
|
||||
export const ollamaRecommendedModels = ['qwen2.5-coder:1.5b', 'llama3.1', 'qwq', 'deepseek-r1'] as const satisfies (keyof typeof ollamaModelOptions)[]
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -245,6 +245,17 @@ class VoidSettingsService extends Disposable implements IVoidSettingsService {
|
|||
}
|
||||
|
||||
// the stored data structure might be outdated, so we need to update it here
|
||||
readS = {
|
||||
...readS,
|
||||
settingsOfProvider: {
|
||||
...defaultSettingsOfProvider,
|
||||
...readS.settingsOfProvider,
|
||||
mistral: { // we added mistral
|
||||
...defaultSettingsOfProvider.mistral,
|
||||
...readS.settingsOfProvider.mistral,
|
||||
},
|
||||
} // we added mistral
|
||||
}
|
||||
this.state = readS
|
||||
this.state = _stateWithUpdatedDefaultModels(this.state)
|
||||
this.state = _validatedModelState(this.state);
|
||||
|
|
|
|||
Loading…
Reference in a new issue