Skip to content

Commit

Permalink
Merge pull request #294 from voideditor/model-selection
Browse files Browse the repository at this point in the history
Provider Settings + UX improvements
  • Loading branch information
andrewpareles authored Feb 24, 2025
2 parents 7206209 + 4a43b62 commit 75f30bf
Show file tree
Hide file tree
Showing 37 changed files with 2,895 additions and 2,049 deletions.
13 changes: 9 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@
"node-pty": "1.1.0-beta21",
"ollama": "^0.5.11",
"open": "^8.4.2",
"openai": "^4.76.1",
"openai": "^4.85.4",
"posthog-node": "^4.3.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ export class EditorGroupWatermark extends Disposable {

const keys3 = this.keybindingService.lookupKeybinding('workbench.action.openGlobalKeybindings');
const button3 = append(recentsBox, $('button'));
button3.textContent = 'Void Settings'
button3.textContent = `Void Settings`
button3.style.display = 'block'
button3.style.marginLeft = 'auto'
button3.style.marginRight = 'auto'
Expand Down
16 changes: 16 additions & 0 deletions src/vs/workbench/contrib/void/browser/MarkerCheckService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { ITextModelService } from '../../../../editor/common/services/resolverSe
import { Range } from '../../../../editor/common/core/range.js';
import { CancellationToken } from '../../../../base/common/cancellation.js';
import { CodeActionContext, CodeActionTriggerType } from '../../../../editor/common/languages.js';
import { URI } from '../../../../base/common/uri.js';

export interface IMarkerCheckService {
readonly _serviceBrand: undefined;
Expand Down Expand Up @@ -99,6 +100,21 @@ class MarkerCheckService extends Disposable implements IMarkerCheckService {
}




fixErrorsInFiles(uris: URI[], contextSoFar: []) {
// const allMarkers = this._markerService.read();


// check errors in files


// give LLM errors in files



}

// private _onMarkersChanged = (changedResources: readonly URI[]): void => {
// for (const resource of changedResources) {
// const markers = this._markerService.read({ resource });
Expand Down
46 changes: 22 additions & 24 deletions src/vs/workbench/contrib/void/browser/autocompleteService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ import { isCodeEditor } from '../../../../editor/browser/editorBrowser.js';
import { EditorResourceAccessor } from '../../../common/editor.js';
import { IModelService } from '../../../../editor/common/services/model.js';
import { extractCodeFromRegular } from './helpers/extractCodeFromResult.js';
import { isWindows } from '../../../../base/common/platform.js';
import { registerWorkbenchContribution2, WorkbenchPhase } from '../../../common/contributions.js';
import { ILLMMessageService } from '../common/llmMessageService.js';
import { _ln, allLinebreakSymbols } from '../common/voidFileService.js';
// import { IContextGatheringService } from './contextGatheringService.js';

// The extension this was called from is here - https://github.com/voideditor/void/blob/autocomplete/extensions/void/src/extension/extension.ts
Expand Down Expand Up @@ -415,9 +415,6 @@ const toInlineCompletions = ({ autocompletionMatchup, autocompletion, prefixAndS
// }


const allLinebreakSymbols = ['\r\n', '\n']
const _ln = isWindows ? allLinebreakSymbols[0] : allLinebreakSymbols[1]

type PrefixAndSuffixInfo = { prefix: string, suffix: string, prefixLines: string[], suffixLines: string[], prefixToTheLeftOfCursor: string, suffixToTheRightOfCursor: string }
const getPrefixAndSuffixInfo = (model: ITextModel, position: Position): PrefixAndSuffixInfo => {

Expand Down Expand Up @@ -798,26 +795,27 @@ export class AutocompleteService extends Disposable implements IAutocompleteServ
},
useProviderFor: 'Autocomplete',
logging: { loggingName: 'Autocomplete' },
onText: async ({ fullText, newText }) => {

newAutocompletion.insertText = fullText

// count newlines in newText
const numNewlines = newText.match(/\n|\r\n/g)?.length || 0
newAutocompletion._newlineCount += numNewlines

// if too many newlines, resolve up to last newline
if (newAutocompletion._newlineCount > 10) {
const lastNewlinePos = fullText.lastIndexOf('\n')
newAutocompletion.insertText = fullText.substring(0, lastNewlinePos)
resolve(newAutocompletion.insertText)
return
}

// if (!getAutocompletionMatchup({ prefix: this._lastPrefix, autocompletion: newAutocompletion })) {
// reject('LLM response did not match user\'s text.')
// }
},
onText: () => { }, // unused in FIMMessage
// onText: async ({ fullText, newText }) => {

// newAutocompletion.insertText = fullText

// // count newlines in newText
// const numNewlines = newText.match(/\n|\r\n/g)?.length || 0
// newAutocompletion._newlineCount += numNewlines

// // if too many newlines, resolve up to last newline
// if (newAutocompletion._newlineCount > 10) {
// const lastNewlinePos = fullText.lastIndexOf('\n')
// newAutocompletion.insertText = fullText.substring(0, lastNewlinePos)
// resolve(newAutocompletion.insertText)
// return
// }

// // if (!getAutocompletionMatchup({ prefix: this._lastPrefix, autocompletion: newAutocompletion })) {
// // reject('LLM response did not match user\'s text.')
// // }
// },
onFinalMessage: ({ fullText }) => {

// console.log('____res: ', JSON.stringify(newAutocompletion.insertText))
Expand Down
77 changes: 39 additions & 38 deletions src/vs/workbench/contrib/void/browser/chatThreadService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ import { URI } from '../../../../base/common/uri.js';
import { Emitter, Event } from '../../../../base/common/event.js';
import { IRange } from '../../../../editor/common/core/range.js';
import { ILLMMessageService } from '../common/llmMessageService.js';
import { IModelService } from '../../../../editor/common/services/model.js';
import { chat_userMessageContent, chat_systemMessage, chat_userMessageContentWithAllFilesToo as chat_userMessageContentWithAllFiles, chat_selectionsString } from './prompt/prompts.js';
import { IFileService } from '../../../../platform/files/common/files.js';
import { InternalToolInfo, IToolsService, ToolCallReturnType, ToolFns, ToolName, voidTools } from '../common/toolsService.js';
import { toLLMChatMessage } from '../common/llmMessageTypes.js';
import { IWorkspaceContextService } from '../../../../platform/workspace/common/workspace.js';
import { IVoidFileService } from '../common/voidFileService.js';
import { generateUuid } from '../../../../base/common/uuid.js';


const findLastIndex = <T>(arr: T[], condition: (t: T) => boolean): number => {
Expand Down Expand Up @@ -48,13 +48,13 @@ export type FileSelection = {
export type StagingSelectionItem = CodeSelection | FileSelection


type ToolMessage<T extends ToolName> = {
export type ToolMessage<T extends ToolName> = {
role: 'tool';
name: T; // internal use
params: string; // internal use
id: string; // apis require this tool use id
content: string; // result
result: ToolCallReturnType<T>; // text message of result
result: ToolCallReturnType[T]; // text message of result
}


Expand All @@ -73,8 +73,7 @@ export type ChatMessage =
stagingSelections: StagingSelectionItem[];
isBeingEdited: boolean;
}
}
| {
} | {
role: 'assistant';
content: string | null; // content received from LLM - allowed to be '', will be replaced with (empty)
displayContent: string | null; // content displayed to user (this is the same as content for now) - allowed to be '', will be ignored
Expand All @@ -86,7 +85,7 @@ type UserMessageState = UserMessageType['state']

export const defaultMessageState: UserMessageState = {
stagingSelections: [],
isBeingEdited: false
isBeingEdited: false,
}

// a 'thread' means a chat message history
Expand Down Expand Up @@ -125,7 +124,7 @@ export type ThreadStreamState = {
const newThreadObject = () => {
const now = new Date().toISOString()
return {
id: new Date().getTime().toString(),
id: generateUuid(),
createdAt: now,
lastModified: now,
messages: [],
Expand Down Expand Up @@ -158,16 +157,25 @@ export interface IChatThreadService {
openNewThread(): void;
switchToThread(threadId: string): void;

// you can edit multiple messages
// the one you're currently editing is "focused", and we add items to that one when you press cmd+L.
getFocusedMessageIdx(): number | undefined;
isFocusingMessage(): boolean;
setFocusedMessageIdx(messageIdx: number | undefined): void;

// _useFocusedStagingState(messageIdx?: number | undefined): readonly [StagingInfo, (stagingInfo: StagingInfo) => void];
_useCurrentThreadState(): readonly [ThreadType['state'], (newState: Partial<ThreadType['state']>) => void];
_useCurrentMessageState(messageIdx: number): readonly [UserMessageState, (newState: Partial<UserMessageState>) => void];
// exposed getters/setters
getCurrentMessageState: (messageIdx: number) => UserMessageState
setCurrentMessageState: (messageIdx: number, newState: Partial<UserMessageState>) => void
getCurrentThreadStagingSelections: () => StagingSelectionItem[]
setCurrentThreadStagingSelections: (stagingSelections: StagingSelectionItem[]) => void


// call to edit a message
editUserMessageAndStreamResponse({ userMessage, chatMode, messageIdx }: { userMessage: string, chatMode: ChatMode, messageIdx: number }): Promise<void>;

// call to add a message
addUserMessageAndStreamResponse({ userMessage, chatMode }: { userMessage: string, chatMode: ChatMode }): Promise<void>;

cancelStreaming(threadId: string): void;
dismissStreamError(threadId: string): void;

Expand All @@ -189,8 +197,7 @@ class ChatThreadService extends Disposable implements IChatThreadService {

constructor(
@IStorageService private readonly _storageService: IStorageService,
@IModelService private readonly _modelService: IModelService,
@IFileService private readonly _fileService: IFileService,
@IVoidFileService private readonly _voidFileService: IVoidFileService,
@ILLMMessageService private readonly _llmMessageService: ILLMMessageService,
@IToolsService private readonly _toolsService: IToolsService,
@IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService,
Expand Down Expand Up @@ -358,7 +365,7 @@ class ChatThreadService extends Disposable implements IChatThreadService {
// add user's message to chat history
const instructions = userMessage
const userMessageContent = await chat_userMessageContent(instructions, currSelns)
const selectionsStr = await chat_selectionsString(prevSelns, currSelns, this._modelService, this._fileService)
const selectionsStr = await chat_selectionsString(prevSelns, currSelns, this._voidFileService)
const userMessageFullContent = chat_userMessageContentWithAllFiles(userMessageContent, selectionsStr)

const userHistoryElt: ChatMessage = { role: 'user', content: userMessageContent, displayContent: instructions, selections: currSelns, state: defaultMessageState }
Expand Down Expand Up @@ -423,10 +430,10 @@ class ChatThreadService extends Disposable implements IChatThreadService {

// 1.
let toolResult: Awaited<ReturnType<ToolFns[ToolName]>>
let toolResultVal: ToolCallReturnType<ToolName>
let toolResultVal: ToolCallReturnType[ToolName]
try {
toolResult = await this._toolsService.toolFns[toolName](tool.params)
toolResultVal = toolResult[0]
toolResultVal = toolResult
} catch (error) {
this._setStreamState(threadId, { error })
shouldSendAnotherMessage = false
Expand Down Expand Up @@ -619,33 +626,27 @@ class ChatThreadService extends Disposable implements IChatThreadService {

}

// gets `staging` and `setStaging` of the currently focused element, given the index of the currently selected message (or undefined if no message is selected)

_useCurrentMessageState(messageIdx: number) {

const thread = this.getCurrentThread()
const messages = thread.messages
const currMessage = messages[messageIdx]

if (currMessage.role !== 'user') {
return [defaultMessageState, (s: any) => { }] as const
}

const state = currMessage.state
const setState = (newState: Partial<UserMessageState>) => this._setCurrentMessageState(newState, messageIdx)

return [state, setState] as const

getCurrentThreadStagingSelections = () => {
return this.getCurrentThread().state.stagingSelections
}

_useCurrentThreadState() {
const thread = this.getCurrentThread()
setCurrentThreadStagingSelections = (stagingSelections: StagingSelectionItem[]) => {
this._setCurrentThreadState({ stagingSelections })
}

const state = thread.state
const setState = this._setCurrentThreadState.bind(this)
// gets `staging` and `setStaging` of the currently focused element, given the index of the currently selected message (or undefined if no message is selected)

return [state, setState] as const
getCurrentMessageState(messageIdx: number): UserMessageState {
const currMessage = this.getCurrentThread()?.messages?.[messageIdx]
if (!currMessage || currMessage.role !== 'user') return defaultMessageState
return currMessage.state
}
setCurrentMessageState(messageIdx: number, newState: Partial<UserMessageState>) {
const currMessage = this.getCurrentThread()?.messages?.[messageIdx]
if (!currMessage || currMessage.role !== 'user') return
this._setCurrentMessageState(newState, messageIdx)
}



}
Expand Down
Loading

0 comments on commit 75f30bf

Please sign in to comment.