mirror of
https://github.com/voideditor/void
synced 2026-05-24 09:58:23 +00:00
error state, sendLLMMessage fix, continue adding state for provider/model pair selection
This commit is contained in:
parent
49b43820b2
commit
bb4f99f687
37 changed files with 333 additions and 196 deletions
|
|
@ -1245,7 +1245,6 @@ export class CodeApplication extends Disposable {
|
|||
// Void
|
||||
const metricsChannel = ProxyChannel.fromService(accessor.get(IMetricsService), disposables);
|
||||
mainProcessElectronServer.registerChannel('void-channel-metrics', metricsChannel);
|
||||
|
||||
const sendLLMMessageChannel = new LLMMessageChannel(accessor.get(IMetricsService));
|
||||
mainProcessElectronServer.registerChannel('void-channel-sendLLMMessage', sendLLMMessageChannel);
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ import { generateUuid } from '../../../base/common/uuid.js';
|
|||
import { createDecorator } from '../../instantiation/common/instantiation.js';
|
||||
import { Event } from '../../../base/common/event.js';
|
||||
import { Disposable } from '../../../base/common/lifecycle.js';
|
||||
import { IVoidConfigStateService } from '../common/voidConfigService.js';
|
||||
import { INotificationService } from '../../notification/common/notification.js';
|
||||
|
||||
|
||||
// BROWSER IMPLEMENTATION OF SENDLLMMESSAGE
|
||||
|
|
@ -19,7 +21,7 @@ export const ISendLLMMessageService = createDecorator<ISendLLMMessageService>('s
|
|||
// defines an interface that node/ creates and browser/ uses
|
||||
export interface ISendLLMMessageService {
|
||||
readonly _serviceBrand: undefined;
|
||||
sendLLMMessage: (params: LLMMessageServiceParams) => string;
|
||||
sendLLMMessage: (params: LLMMessageServiceParams) => string | null;
|
||||
abort: (requestId: string) => void;
|
||||
}
|
||||
|
||||
|
|
@ -34,12 +36,14 @@ export class SendLLMMessageService extends Disposable implements ISendLLMMessage
|
|||
private readonly onErrorHooks: { [eventId: string]: ((params: ProxyOnErrorPayload) => void) } = {}
|
||||
|
||||
constructor(
|
||||
@IMainProcessService mainProcessService: IMainProcessService // used as a renderer (only usable on client side)
|
||||
@IMainProcessService private readonly mainProcessService: IMainProcessService, // used as a renderer (only usable on client side)
|
||||
@IVoidConfigStateService private readonly voidConfigStateService: IVoidConfigStateService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
) {
|
||||
super()
|
||||
|
||||
// const service = ProxyChannel.toService<LLMMessageChannel>(mainProcessService.getChannel('void-channel-sendLLMMessage')); // lets you call it like a service
|
||||
this.channel = mainProcessService.getChannel('void-channel-sendLLMMessage')
|
||||
this.channel = this.mainProcessService.getChannel('void-channel-sendLLMMessage')
|
||||
|
||||
// this sets up an IPC channel and takes a few ms, so we set up listeners immediately and add hooks to them instead
|
||||
const onTextEvent: Event<ProxyOnTextPayload> = this.channel.listen('onText')
|
||||
|
|
@ -77,9 +81,25 @@ export class SendLLMMessageService extends Disposable implements ISendLLMMessage
|
|||
this.onFinalMessageHooks[requestId_] = onFinalMessage
|
||||
this.onErrorHooks[requestId_] = onError
|
||||
|
||||
const { featureName } = params
|
||||
|
||||
// params will be stripped of all its functions
|
||||
this.channel.call('sendLLMMessage', { ...proxyParams, requestId: requestId_ } satisfies ProxyLLMMessageParams);
|
||||
const stateOfFeature = this.voidConfigStateService.state.modelSelectionOfFeature[featureName]
|
||||
if (stateOfFeature === null) {
|
||||
this.notificationService.warn('Please add a Provider in Settings!')
|
||||
return null
|
||||
}
|
||||
const { providerName, modelName } = stateOfFeature
|
||||
|
||||
const { settingsOfProvider } = this.voidConfigStateService.state
|
||||
|
||||
this.channel.call('sendLLMMessage', {
|
||||
...proxyParams,
|
||||
requestId: requestId_,
|
||||
providerName,
|
||||
modelName,
|
||||
settingsOfProvider,
|
||||
} satisfies ProxyLLMMessageParams);
|
||||
|
||||
return requestId_
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,10 @@
|
|||
* Void Editor additions licensed under the AGPLv3 License.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ProviderName, VoidProviderState } from './configTypes'
|
||||
import { IRange } from '../../../editor/common/core/range'
|
||||
import { ProviderName, SettingsOfProvider } from './voidConfigTypes'
|
||||
|
||||
|
||||
// ---------- type definitions ----------
|
||||
|
||||
export type OnText = (p: { newText: string, fullText: string }) => void
|
||||
|
||||
export type OnFinalMessage = (p: { fullText: string }) => void
|
||||
|
|
@ -21,42 +20,67 @@ export type LLMMessage = {
|
|||
content: string;
|
||||
}
|
||||
|
||||
export type LLMFeatureSelection = {
|
||||
featureName: 'Ctrl+K',
|
||||
range: IRange
|
||||
} | {
|
||||
featureName: 'Ctrl+L',
|
||||
} | {
|
||||
featureName: 'Autocomplete',
|
||||
range: IRange
|
||||
}
|
||||
|
||||
export type LLMMessageServiceParams = {
|
||||
onText: OnText;
|
||||
onFinalMessage: OnFinalMessage;
|
||||
onError: OnError;
|
||||
|
||||
messages: LLMMessage[];
|
||||
voidConfig: VoidProviderState | null;
|
||||
|
||||
logging: {
|
||||
loggingName: string,
|
||||
};
|
||||
providerName: ProviderName;
|
||||
|
||||
}
|
||||
} & LLMFeatureSelection
|
||||
|
||||
// params to the true sendLLMMessage function
|
||||
export type SendLLMMMessageParams = {
|
||||
onText: OnText;
|
||||
onFinalMessage: OnFinalMessage;
|
||||
onError: OnError;
|
||||
abortRef: AbortRef;
|
||||
|
||||
messages: LLMMessage[];
|
||||
voidConfig: VoidProviderState | null;
|
||||
|
||||
logging: {
|
||||
loggingName: string,
|
||||
};
|
||||
providerName: ProviderName;
|
||||
abortRef: AbortRef;
|
||||
modelName: string;
|
||||
settingsOfProvider: SettingsOfProvider;
|
||||
}
|
||||
|
||||
// can't send functions across a proxy, use listeners instead
|
||||
export const listenerNames = ['onText', 'onFinalMessage', 'onError'] as const
|
||||
export type ProxyLLMMessageParams = Omit<LLMMessageServiceParams, typeof listenerNames[number]> & { requestId: string }
|
||||
export type BlockedProxyParams = 'onText' | 'onFinalMessage' | 'onError' | 'abortRef'
|
||||
export type ProxyLLMMessageParams = Omit<SendLLMMMessageParams, BlockedProxyParams> & { requestId: string }
|
||||
|
||||
export type ProxyOnTextPayload = Parameters<OnText>[0] & { requestId: string }
|
||||
export type ProxyOnFinalMessagePayload = Parameters<OnFinalMessage>[0] & { requestId: string }
|
||||
export type ProxyOnErrorPayload = Parameters<OnError>[0] & { requestId: string }
|
||||
|
||||
export type ProxyLLMMessageAbortParams = { requestId: string }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export type SendLLMMessageFnTypeInternal = (params: {
|
||||
messages: LLMMessage[];
|
||||
onText: OnText;
|
||||
onFinalMessage: OnFinalMessage;
|
||||
onError: OnError;
|
||||
settingsOfProvider: SettingsOfProvider;
|
||||
providerName: ProviderName;
|
||||
modelName: string;
|
||||
|
||||
_setAborter: (aborter: () => void) => void;
|
||||
}) => void
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Glass Devtools, Inc. All rights reserved.
|
||||
* Void Editor additions licensed under the AGPLv3 License.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { createDecorator } from '../../instantiation/common/instantiation.js';
|
||||
|
||||
export interface IMetricsService {
|
||||
|
|
|
|||
|
|
@ -3,15 +3,14 @@
|
|||
* Void Editor additions licensed under the AGPLv3 License.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter, Event } from '../../../../base/common/event.js';
|
||||
import { Disposable } from '../../../../base/common/lifecycle.js';
|
||||
import { deepClone } from '../../../../base/common/objects.js';
|
||||
import { IEncryptionService } from '../../../../platform/encryption/common/encryptionService.js';
|
||||
import { registerSingleton, InstantiationType } from '../../../../platform/instantiation/common/extensions.js';
|
||||
import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';
|
||||
import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js';
|
||||
import { defaultVoidProviderState, FeatureName, ProviderName, ModelSelectionOfFeature, SettingsOfProvider } from '../../../../platform/void/common/configTypes.js';
|
||||
|
||||
import { Emitter, Event } from '../../../base/common/event.js';
|
||||
import { Disposable } from '../../../base/common/lifecycle.js';
|
||||
import { deepClone } from '../../../base/common/objects.js';
|
||||
import { IEncryptionService } from '../../encryption/common/encryptionService.js';
|
||||
import { registerSingleton, InstantiationType } from '../../instantiation/common/extensions.js';
|
||||
import { createDecorator } from '../../instantiation/common/instantiation.js';
|
||||
import { IStorageService, StorageScope, StorageTarget } from '../../storage/common/storage.js';
|
||||
import { defaultVoidProviderState, FeatureName, ProviderName, ModelSelectionOfFeature, SettingsOfProvider } from './voidConfigTypes.js';
|
||||
|
||||
|
||||
const CONFIG_STORAGE_KEY = 'void.voidConfigStateII'
|
||||
|
|
@ -89,7 +88,7 @@ class VoidConfigStateService extends Disposable implements IVoidConfigStateServi
|
|||
|
||||
private async _storeVoidConfigState(voidConfigState: VoidConfigState) {
|
||||
const encryptedVoidConfigStr = await this._encryptionService.encrypt(JSON.stringify(voidConfigState))
|
||||
this._storageService.store(CONFIG_STORAGE_KEY, encryptedVoidConfigStr, StorageScope.APPLICATION, StorageTarget.USER)
|
||||
this._storageService.store(CONFIG_STORAGE_KEY, encryptedVoidConfigStr, StorageScope.APPLICATION, StorageTarget.USER);
|
||||
}
|
||||
|
||||
setSettingOfProvider: SetSettingOfProviderFn = async (providerName, option, newVal) => {
|
||||
|
|
@ -1,14 +1,15 @@
|
|||
import Anthropic from '@anthropic-ai/sdk';
|
||||
import { parseMaxTokensStr, SendLLMMessageFnTypeInternal } from './util.js';
|
||||
import { parseMaxTokensStr } from './util.js';
|
||||
import { SendLLMMessageFnTypeInternal } from '../../common/llmMessageTypes.js';
|
||||
|
||||
// Anthropic
|
||||
type LLMMessageAnthropic = {
|
||||
role: 'user' | 'assistant';
|
||||
content: string;
|
||||
}
|
||||
export const sendAnthropicMsg: SendLLMMessageFnTypeInternal = ({ messages, onText, onFinalMessage, onError, voidConfig, _setAborter }) => {
|
||||
export const sendAnthropicMsg: SendLLMMessageFnTypeInternal = ({ messages, onText, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter }) => {
|
||||
|
||||
const thisConfig = voidConfig.anthropic
|
||||
const thisConfig = settingsOfProvider.anthropic
|
||||
|
||||
const anthropic = new Anthropic({ apiKey: thisConfig.apiKey, dangerouslyAllowBrowser: true });
|
||||
|
||||
|
|
@ -24,7 +25,7 @@ export const sendAnthropicMsg: SendLLMMessageFnTypeInternal = ({ messages, onTex
|
|||
const stream = anthropic.messages.stream({
|
||||
system: systemMessage,
|
||||
messages: anthropicMessages,
|
||||
model: thisConfig.model,
|
||||
model: modelName,
|
||||
max_tokens: parseMaxTokensStr(thisConfig.maxTokens)!, // this might be undefined, but it will just throw an error for the user to see
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
import { Content, GoogleGenerativeAI, GoogleGenerativeAIFetchError } from '@google/generative-ai';
|
||||
import { SendLLMMessageFnTypeInternal } from './util';
|
||||
import { SendLLMMessageFnTypeInternal } from '../../common/llmMessageTypes.js';
|
||||
|
||||
// Gemini
|
||||
export const sendGeminiMsg: SendLLMMessageFnTypeInternal = async ({ messages, onText, onFinalMessage, onError, voidConfig, _setAborter }) => {
|
||||
export const sendGeminiMsg: SendLLMMessageFnTypeInternal = async ({ messages, onText, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter }) => {
|
||||
|
||||
let fullText = ''
|
||||
|
||||
const thisConfig = voidConfig.gemini
|
||||
const thisConfig = settingsOfProvider.gemini
|
||||
|
||||
const genAI = new GoogleGenerativeAI(thisConfig.apiKey);
|
||||
const model = genAI.getGenerativeModel({ model: thisConfig.model });
|
||||
const model = genAI.getGenerativeModel({ model: modelName });
|
||||
|
||||
// remove system messages that get sent to Gemini
|
||||
// str of all system messages
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@
|
|||
// // https://docs.greptile.com/api-reference/query
|
||||
// // https://docs.greptile.com/quickstart#sample-response-streamed
|
||||
|
||||
// import { SendLLMMessageFnTypeInternal } from './util';
|
||||
// import { SendLLMMessageFnTypeInternal } from '../../common/llmMessageTypes.js';
|
||||
|
||||
// export const sendGreptileMsg: SendLLMMessageFnTypeInternal = ({ messages, onText, onFinalMessage, onError, voidConfig, _setAborter }) => {
|
||||
// export const sendGreptileMsg: SendLLMMessageFnTypeInternal = ({ messages, onText, onFinalMessage, onError, settingsOfProvider, _setAborter }) => {
|
||||
|
||||
// let fullText = ''
|
||||
|
||||
// const thisConfig = voidConfig.greptile
|
||||
// const thisConfig = settingsOfProvider.greptile
|
||||
|
||||
// fetch('https://api.greptile.com/v2/query', {
|
||||
// method: 'POST',
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import Groq from 'groq-sdk';
|
||||
import { SendLLMMessageFnTypeInternal } from './util';
|
||||
import { SendLLMMessageFnTypeInternal } from '../../common/llmMessageTypes.js';
|
||||
import { parseMaxTokensStr } from './util.js';
|
||||
|
||||
// Groq
|
||||
export const sendGroqMsg: SendLLMMessageFnTypeInternal = async ({ messages, onText, onFinalMessage, onError, voidConfig, _setAborter }) => {
|
||||
export const sendGroqMsg: SendLLMMessageFnTypeInternal = async ({ messages, onText, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter }) => {
|
||||
let fullText = '';
|
||||
|
||||
const thisConfig = voidConfig.groq
|
||||
const thisConfig = settingsOfProvider.groq
|
||||
|
||||
const groq = new Groq({
|
||||
apiKey: thisConfig.apiKey,
|
||||
|
|
@ -16,7 +16,7 @@ export const sendGroqMsg: SendLLMMessageFnTypeInternal = async ({ messages, onTe
|
|||
await groq.chat.completions
|
||||
.create({
|
||||
messages: messages,
|
||||
model: thisConfig.model,
|
||||
model: modelName,
|
||||
stream: true,
|
||||
temperature: 0.7,
|
||||
max_tokens: parseMaxTokensStr(thisConfig.maxTokens),
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
import { Ollama } from 'ollama';
|
||||
import { SendLLMMessageFnTypeInternal } from './util';
|
||||
import { SendLLMMessageFnTypeInternal } from '../../common/llmMessageTypes.js';
|
||||
import { parseMaxTokensStr } from './util.js';
|
||||
|
||||
// Ollama
|
||||
export const sendOllamaMsg: SendLLMMessageFnTypeInternal = ({ messages, onText, onFinalMessage, onError, voidConfig, _setAborter }) => {
|
||||
export const sendOllamaMsg: SendLLMMessageFnTypeInternal = ({ messages, onText, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter }) => {
|
||||
|
||||
const thisConfig = voidConfig.ollama
|
||||
const thisConfig = settingsOfProvider.ollama
|
||||
|
||||
let fullText = ''
|
||||
|
||||
const ollama = new Ollama({ host: thisConfig.endpoint })
|
||||
|
||||
ollama.chat({
|
||||
model: thisConfig.model,
|
||||
model: modelName,
|
||||
messages: messages,
|
||||
stream: true,
|
||||
options: { num_predict: parseMaxTokensStr(thisConfig.maxTokens) } // this is max_tokens
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import OpenAI from 'openai';
|
||||
import { SendLLMMessageFnTypeInternal } from './util';
|
||||
import { SendLLMMessageFnTypeInternal } from '../../common/llmMessageTypes.js';
|
||||
import { parseMaxTokensStr } from './util.js';
|
||||
|
||||
|
||||
// OpenAI, OpenRouter, OpenAICompatible
|
||||
export const sendOpenAIMsg: SendLLMMessageFnTypeInternal = ({ messages, onText, onFinalMessage, onError, voidConfig, _setAborter, providerName }) => {
|
||||
export const sendOpenAIMsg: SendLLMMessageFnTypeInternal = ({ messages, onText, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter, providerName }) => {
|
||||
|
||||
let fullText = ''
|
||||
|
||||
|
|
@ -13,12 +13,12 @@ export const sendOpenAIMsg: SendLLMMessageFnTypeInternal = ({ messages, onText,
|
|||
|
||||
|
||||
if (providerName === 'openAI') {
|
||||
const thisConfig = voidConfig.openAI
|
||||
const thisConfig = settingsOfProvider.openAI
|
||||
openai = new OpenAI({ apiKey: thisConfig.apiKey, dangerouslyAllowBrowser: true });
|
||||
options = { model: thisConfig.model, messages: messages, stream: true, max_completion_tokens: parseMaxTokensStr(thisConfig.maxTokens) }
|
||||
options = { model: modelName, messages: messages, stream: true, max_completion_tokens: parseMaxTokensStr(thisConfig.maxTokens) }
|
||||
}
|
||||
else if (providerName === 'openRouter') {
|
||||
const thisConfig = voidConfig.openRouter
|
||||
const thisConfig = settingsOfProvider.openRouter
|
||||
openai = new OpenAI({
|
||||
baseURL: 'https://openrouter.ai/api/v1', apiKey: thisConfig.apiKey, dangerouslyAllowBrowser: true,
|
||||
defaultHeaders: {
|
||||
|
|
@ -26,12 +26,12 @@ export const sendOpenAIMsg: SendLLMMessageFnTypeInternal = ({ messages, onText,
|
|||
'X-Title': 'Void Editor', // Optional. Shows in rankings on openrouter.ai.
|
||||
},
|
||||
});
|
||||
options = { model: thisConfig.model, messages: messages, stream: true, max_completion_tokens: parseMaxTokensStr(thisConfig.maxTokens) }
|
||||
options = { model: modelName, messages: messages, stream: true, max_completion_tokens: parseMaxTokensStr(thisConfig.maxTokens) }
|
||||
}
|
||||
else if (providerName === 'openAICompatible') {
|
||||
const thisConfig = voidConfig.openAICompatible
|
||||
const thisConfig = settingsOfProvider.openAICompatible
|
||||
openai = new OpenAI({ baseURL: thisConfig.endpoint, apiKey: thisConfig.apiKey, dangerouslyAllowBrowser: true })
|
||||
options = { model: thisConfig.model, messages: messages, stream: true, max_completion_tokens: parseMaxTokensStr(thisConfig.maxTokens) }
|
||||
options = { model: modelName, messages: messages, stream: true, max_completion_tokens: parseMaxTokensStr(thisConfig.maxTokens) }
|
||||
}
|
||||
else {
|
||||
console.error(`sendOpenAIMsg: invalid providerName: ${providerName}`)
|
||||
|
|
|
|||
|
|
@ -13,14 +13,14 @@ export const sendLLMMessage = ({
|
|||
onFinalMessage: onFinalMessage_,
|
||||
onError: onError_,
|
||||
abortRef: abortRef_,
|
||||
voidConfig,
|
||||
logging: { loggingName },
|
||||
providerName
|
||||
settingsOfProvider,
|
||||
providerName,
|
||||
modelName,
|
||||
}: SendLLMMMessageParams,
|
||||
|
||||
metricsService: IMetricsService
|
||||
) => {
|
||||
if (!voidConfig) return;
|
||||
|
||||
// trim message content (Anthropic and other providers give an error if there is trailing whitespace)
|
||||
messages = messages.map(m => ({ ...m, content: m.content.trim() }))
|
||||
|
|
@ -74,21 +74,21 @@ export const sendLLMMessage = ({
|
|||
try {
|
||||
switch (providerName) {
|
||||
case 'anthropic':
|
||||
sendAnthropicMsg({ messages, onText, onFinalMessage, onError, voidConfig, _setAborter, providerName });
|
||||
sendAnthropicMsg({ messages, onText, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter, providerName });
|
||||
break;
|
||||
case 'openAI':
|
||||
case 'openRouter':
|
||||
case 'openAICompatible':
|
||||
sendOpenAIMsg({ messages, onText, onFinalMessage, onError, voidConfig, _setAborter, providerName });
|
||||
sendOpenAIMsg({ messages, onText, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter, providerName });
|
||||
break;
|
||||
case 'gemini':
|
||||
sendGeminiMsg({ messages, onText, onFinalMessage, onError, voidConfig, _setAborter, providerName });
|
||||
sendGeminiMsg({ messages, onText, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter, providerName });
|
||||
break;
|
||||
case 'ollama':
|
||||
sendOllamaMsg({ messages, onText, onFinalMessage, onError, voidConfig, _setAborter, providerName });
|
||||
sendOllamaMsg({ messages, onText, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter, providerName });
|
||||
break;
|
||||
case 'groq':
|
||||
sendGroqMsg({ messages, onText, onFinalMessage, onError, voidConfig, _setAborter, providerName });
|
||||
sendGroqMsg({ messages, onText, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter, providerName });
|
||||
break;
|
||||
default:
|
||||
onError({ error: `Error: whichApi was "${providerName}", which is not recognized!` })
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
import { ProviderName, VoidProviderState } from '../../common/configTypes'
|
||||
import { LLMMessage, OnText, OnFinalMessage, OnError } from '../../common/llmMessageTypes'
|
||||
|
||||
export const parseMaxTokensStr = (maxTokensStr: string) => {
|
||||
// parse the string but only if the full string is a valid number, eg parseInt('100abc') should return NaN
|
||||
const int = isNaN(Number(maxTokensStr)) ? undefined : parseInt(maxTokensStr)
|
||||
|
|
@ -10,13 +7,3 @@ export const parseMaxTokensStr = (maxTokensStr: string) => {
|
|||
}
|
||||
|
||||
|
||||
export type SendLLMMessageFnTypeInternal = (params: {
|
||||
messages: LLMMessage[];
|
||||
onText: OnText;
|
||||
onFinalMessage: OnFinalMessage;
|
||||
onError: OnError;
|
||||
voidConfig: VoidProviderState;
|
||||
providerName: ProviderName;
|
||||
|
||||
_setAborter: (aborter: () => void) => void;
|
||||
}) => void
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import { IServerChannel } from '../../../base/parts/ipc/common/ipc.js';
|
||||
import { Emitter, Event } from '../../../base/common/event.js';
|
||||
import { listenerNames, ProxyOnTextPayload, ProxyOnErrorPayload, ProxyOnFinalMessagePayload, ProxyLLMMessageParams, AbortRef, SendLLMMMessageParams, ProxyLLMMessageAbortParams } from '../common/llmMessageTypes.js';
|
||||
import { BlockedProxyParams, ProxyOnTextPayload, ProxyOnErrorPayload, ProxyOnFinalMessagePayload, ProxyLLMMessageParams, AbortRef, SendLLMMMessageParams, ProxyLLMMessageAbortParams } from '../common/llmMessageTypes.js';
|
||||
import { sendLLMMessage } from './llmMessage/sendLLMMessage.js'
|
||||
import { IMetricsService } from '../common/metricsService.js';
|
||||
|
||||
|
|
@ -28,12 +28,15 @@ export class LLMMessageChannel implements IServerChannel {
|
|||
private readonly _abortRefOfRequestId: Record<string, AbortRef> = {}
|
||||
|
||||
|
||||
// stupidly, channels can't take in @IService
|
||||
constructor(
|
||||
private readonly metricsService: IMetricsService
|
||||
) { }
|
||||
private readonly metricsService: IMetricsService,
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
// browser uses this to listen for changes
|
||||
listen(_: unknown, event: typeof listenerNames[number]): Event<any> {
|
||||
listen(_: unknown, event: BlockedProxyParams): Event<any> {
|
||||
if (event === 'onText') {
|
||||
return this.onText;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -742,18 +742,6 @@ export class CodeWindow extends BaseWindow implements ICodeWindow {
|
|||
cb({ cancel: false, requestHeaders: Object.assign(details.requestHeaders, headers) });
|
||||
});
|
||||
|
||||
|
||||
// // Void: send from https://
|
||||
// this._win.webContents.session.webRequest.onBeforeSendHeaders({ urls }, async (details, cb) => {
|
||||
// // const voidConfig = this.voidConfigStateService.state.voidConfig
|
||||
// // const whichApi = voidConfig.default['whichApi']
|
||||
// const endpoint = 'http://127.' //string | undefined = voidConfig[whichApi as VoidConfigField].endpoint
|
||||
|
||||
// if (endpoint && details.url.startsWith(endpoint)) {
|
||||
// details.requestHeaders['Origin'] = 'https://app.voideditor.com'
|
||||
// }
|
||||
// cb({ cancel: false, requestHeaders: details.requestHeaders });
|
||||
// });
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,9 @@
|
|||
.monaco-editor .void-sweepIdxBG {
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Glass Devtools, Inc. All rights reserved.
|
||||
* Void Editor additions licensed under the AGPLv3 License.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-editor .void-sweepIdxBG {
|
||||
background-color: var(--vscode-void-sweepIdxBG);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Glass Devtools, Inc. All rights reserved.
|
||||
* Void Editor additions licensed under the AGPLv3 License.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { CodeSelection } from '../registerThreads.js';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Glass Devtools, Inc. All rights reserved.
|
||||
* Void Editor additions licensed under the AGPLv3 License.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
// // used for ctrl+l
|
||||
// const partialGenerationInstructions = ``
|
||||
|
|
@ -9,6 +11,31 @@
|
|||
// const fimInstructions = ``
|
||||
|
||||
|
||||
// CTRL+K prompt:
|
||||
// const promptContent = `Here is the user's original selection:
|
||||
// \`\`\`
|
||||
// <MID>${selection}</MID>
|
||||
// \`\`\`
|
||||
|
||||
// The user wants to apply the following instructions to the selection:
|
||||
// ${instructions}
|
||||
|
||||
// Please rewrite the selection following the user's instructions.
|
||||
|
||||
// Instructions to follow:
|
||||
// 1. Follow the user's instructions
|
||||
// 2. You may ONLY CHANGE the selection, and nothing else in the file
|
||||
// 3. Make sure all brackets in the new selection are balanced the same was as in the original selection
|
||||
// 3. Be careful not to duplicate or remove variables, comments, or other syntax by mistake
|
||||
|
||||
// Complete the following:
|
||||
// \`\`\`
|
||||
// <PRE>${prefix}</PRE>
|
||||
// <SUF>${suffix}</SUF>
|
||||
// <MID>`;
|
||||
|
||||
|
||||
|
||||
export const generateDiffInstructions = `
|
||||
You are a coding assistant. You are given a list of relevant files \`files\`, a selection that the user is making \`selection\`, and instructions to follow \`instructions\`.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Glass Devtools, Inc. All rights reserved.
|
||||
* Void Editor additions licensed under the AGPLv3 License.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import React, { JSX, useCallback, useEffect, useState } from 'react'
|
||||
import { marked, MarkedToken, Token } from 'marked'
|
||||
import { BlockCode } from './BlockCode.js'
|
||||
|
|
@ -44,7 +49,7 @@ const CodeButtonsOnHover = ({ diffRepr: text }: { diffRepr: string }) => {
|
|||
className="btn btn-secondary btn-sm border border-vscode-input-border rounded"
|
||||
onClick={async () => {
|
||||
|
||||
inlineDiffService.startStreaming({ type: 'ctrl+l', providerName: 'anthropic' }, text)
|
||||
inlineDiffService.startStreaming({ featureName: 'Ctrl+L' }, text)
|
||||
}}
|
||||
>
|
||||
Apply
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Glass Devtools, Inc. All rights reserved.
|
||||
* Void Editor additions licensed under the AGPLv3 License.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import React, { Component, ErrorInfo, ReactNode } from 'react';
|
||||
import { ErrorDisplay } from './ErrorDisplay.js';
|
||||
|
||||
interface Props {
|
||||
children: ReactNode;
|
||||
fallback?: ReactNode;
|
||||
onDismiss?: () => void;
|
||||
}
|
||||
|
||||
interface State {
|
||||
hasError: boolean;
|
||||
error: Error | null;
|
||||
errorInfo: ErrorInfo | null;
|
||||
}
|
||||
|
||||
class ErrorBoundary extends Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
hasError: false,
|
||||
error: null,
|
||||
errorInfo: null
|
||||
};
|
||||
}
|
||||
|
||||
static getDerivedStateFromError(error: Error): Partial<State> {
|
||||
return {
|
||||
hasError: true,
|
||||
error
|
||||
};
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
|
||||
this.setState({
|
||||
error,
|
||||
errorInfo
|
||||
});
|
||||
}
|
||||
|
||||
render(): ReactNode {
|
||||
if (this.state.hasError && this.state.error) {
|
||||
// If a custom fallback is provided, use it
|
||||
if (this.props.fallback) {
|
||||
return this.props.fallback;
|
||||
}
|
||||
|
||||
// Use ErrorDisplay component as the default error UI
|
||||
return (
|
||||
<ErrorDisplay
|
||||
error={this.state.error}
|
||||
onDismiss={this.props.onDismiss || null}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
export default ErrorBoundary;
|
||||
|
|
@ -1,3 +1,8 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Glass Devtools, Inc. All rights reserved.
|
||||
* Void Editor additions licensed under the AGPLv3 License.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { AlertCircle, ChevronDown, ChevronUp, X } from 'lucide-react';
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import { SidebarThreadSelector } from './SidebarThreadSelector.js';
|
|||
import { SidebarChat } from './SidebarChat.js';
|
||||
import { SidebarModelSettings } from './SidebarModelSettings.js';
|
||||
import { SidebarProviderSettings } from './SidebarProviderSettings.js';
|
||||
import ErrorBoundary from './ErrorBoundary.js';
|
||||
|
||||
const Sidebar = () => {
|
||||
const sidebarState = useSidebarState()
|
||||
|
|
@ -33,17 +34,25 @@ const Sidebar = () => {
|
|||
}}>clickme {tab}</span> */}
|
||||
|
||||
<div className={`mb-2 ${isHistoryOpen ? '' : 'hidden'}`}>
|
||||
<SidebarThreadSelector />
|
||||
<ErrorBoundary>
|
||||
<SidebarThreadSelector />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
|
||||
<div className={`${tab === 'chat' ? '' : 'hidden'}`}>
|
||||
<SidebarChat />
|
||||
<ErrorBoundary>
|
||||
<SidebarChat />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
|
||||
<div className={`${tab === 'settings' ? '' : 'hidden'}`}>
|
||||
<SidebarModelSettings />
|
||||
<ErrorBoundary>
|
||||
<SidebarModelSettings />
|
||||
</ErrorBoundary>
|
||||
--------
|
||||
<SidebarProviderSettings />
|
||||
<ErrorBoundary>
|
||||
<SidebarProviderSettings />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
* Copyright (c) Glass Devtools, Inc. All rights reserved.
|
||||
* Void Editor additions licensed under the AGPLv3 License.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import React, { FormEvent, Fragment, useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
|
||||
|
|
@ -219,8 +220,8 @@ export const SidebarChat = () => {
|
|||
|
||||
setLatestError(error)
|
||||
},
|
||||
voidConfig: voidConfigState,
|
||||
providerName: 'anthropic',
|
||||
featureName: 'Ctrl+L',
|
||||
|
||||
}
|
||||
|
||||
const latestRequestId = sendLLMMessageService.sendLLMMessage(object)
|
||||
|
|
|
|||
|
|
@ -3,14 +3,17 @@
|
|||
* Void Editor additions licensed under the AGPLv3 License.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { FeatureName, featureNames, providerNames } from '../../../../../../../platform/void/common/configTypes.js'
|
||||
import { useConfigState } from '../util/services.js'
|
||||
import { FeatureName, featureNames, providerNames } from '../../../../../../../platform/void/common/voidConfigTypes.js'
|
||||
import { useConfigState, useService } from '../util/services.js'
|
||||
import ErrorBoundary from './ErrorBoundary.js'
|
||||
import { VoidSelectBox } from './inputs.js'
|
||||
|
||||
|
||||
|
||||
|
||||
export const SidebarModelSettingsForFeature = ({ featureName }: { featureName: FeatureName }) => {
|
||||
|
||||
const voidConfigService = useService('configStateService')
|
||||
const voidConfigState = useConfigState()
|
||||
|
||||
const models: [string, string][] = []
|
||||
|
|
@ -22,10 +25,21 @@ export const SidebarModelSettingsForFeature = ({ featureName }: { featureName: F
|
|||
})
|
||||
}
|
||||
|
||||
return <>
|
||||
<h1>Settings - {featureName}</h1>
|
||||
{models.map(([providerName, model], i) => <p key={i}>{providerName} - {model}</p>)}
|
||||
</>
|
||||
return <><ErrorBoundary>
|
||||
<h2>{'Models'}</h2>
|
||||
{models.length === 0 ?
|
||||
<p>{'Please add a provider!'}</p>
|
||||
:
|
||||
<VoidSelectBox
|
||||
initVal={models[0].join(' - ')}
|
||||
options={models.map(s => s.join(' - '))}
|
||||
onChangeSelection={(newVal) => { /*voidConfigService.setFeatureState(providerName, 'model', newVal)*/ }}
|
||||
selectBoxRef={{ current: null }}
|
||||
/>}
|
||||
|
||||
{/* <h1>Settings - {featureName}</h1> */}
|
||||
{/* {models.map(([providerName, model], i) => <p key={i}>{providerName} - {model}</p>)} */}
|
||||
</ErrorBoundary></>
|
||||
}
|
||||
|
||||
export const SidebarModelSettings = () => {
|
||||
|
|
|
|||
|
|
@ -4,10 +4,11 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import React, { Fragment, useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { displayInfoOfSettingName, ProviderName, providerNames, ProviderSettingName, VoidProviderState } from '../../../../../../../platform/void/common/configTypes.js'
|
||||
import { displayInfoOfSettingName, ProviderName, providerNames } from '../../../../../../../platform/void/common/voidConfigTypes.js'
|
||||
import { VoidCheckBox, VoidInputBox, VoidSelectBox } from './inputs.js'
|
||||
import { useConfigState, useService } from '../util/services.js'
|
||||
import { InputBox } from '../../../../../../../base/browser/ui/inputbox/inputBox.js'
|
||||
import ErrorBoundary from './ErrorBoundary.js'
|
||||
|
||||
|
||||
const Setting = ({ providerName, settingName }: { providerName: ProviderName, settingName: any }) => {
|
||||
|
|
@ -21,8 +22,12 @@ const Setting = ({ providerName, settingName }: { providerName: ProviderName, se
|
|||
// this is really just to sync the state on initial mount, when init value hasn't been set yet
|
||||
const syncState = () => {
|
||||
if (!instanceRef.current) return
|
||||
|
||||
const settingsAtProvider = voidConfigService.state.settingsOfProvider[providerName];
|
||||
|
||||
// @ts-ignore
|
||||
const stateVal = voidConfigService.state[providerName][settingName]
|
||||
const stateVal = settingsAtProvider[settingName]
|
||||
|
||||
if (instanceRef.current.value !== stateVal)
|
||||
instanceRef.current.value = stateVal
|
||||
}
|
||||
|
|
@ -31,44 +36,30 @@ const Setting = ({ providerName, settingName }: { providerName: ProviderName, se
|
|||
return () => disposable.dispose()
|
||||
}, [instanceRef, voidConfigService])
|
||||
|
||||
return <>
|
||||
return <><ErrorBoundary>
|
||||
<h2>{title}</h2>
|
||||
{<VoidInputBox
|
||||
placeholder={placeholder}
|
||||
onChangeText={useCallback((newVal) => {
|
||||
voidConfigService.setState(providerName, settingName, newVal)
|
||||
voidConfigService.setSettingOfProvider(providerName, settingName, newVal)
|
||||
}, [voidConfigService, providerName, settingName])
|
||||
}
|
||||
onCreateInstance={instanceRef}
|
||||
multiline={false}
|
||||
/>}
|
||||
</>
|
||||
</ErrorBoundary></>
|
||||
|
||||
}
|
||||
|
||||
const SettingsForProvider = ({ providerName }: { providerName: ProviderName }) => {
|
||||
const voidConfigState = useConfigState()
|
||||
const { models, model, ...others } = voidConfigState[providerName]
|
||||
const voidConfigService = useService('configStateService')
|
||||
|
||||
const { models, ...others } = voidConfigState[providerName]
|
||||
return <>
|
||||
<h1>{providerName}</h1>
|
||||
|
||||
{/* other settings (e.g. api key) */}
|
||||
{/* settings besides models (e.g. api key) */}
|
||||
{Object.keys(others).map((settingName, i) => {
|
||||
return <Setting key={settingName} providerName={providerName} settingName={settingName} />
|
||||
})}
|
||||
|
||||
<h2>{'Models'}</h2>
|
||||
{models === null ?
|
||||
<p>{'No models available.'}</p>
|
||||
: <VoidSelectBox
|
||||
initVal={models[0]}
|
||||
options={models}
|
||||
onChangeSelection={(newVal) => { voidConfigService.setState(providerName, 'model', newVal) }}
|
||||
selectBoxRef={{ current: null }}
|
||||
/>}
|
||||
|
||||
</>
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
* Copyright (c) Glass Devtools, Inc. All rights reserved.
|
||||
* Void Editor additions licensed under the AGPLv3 License.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import React from "react";
|
||||
import { useService, useThreadsState } from '../util/services.js';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Glass Devtools, Inc. All rights reserved.
|
||||
* Void Editor additions licensed under the AGPLv3 License.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import React, { useCallback, useEffect, useRef } from 'react';
|
||||
import { useService } from '../util/services.js';
|
||||
import { HistoryInputBox, InputBox } from '../../../../../../../base/browser/ui/inputbox/inputBox.js';
|
||||
|
|
@ -102,7 +107,7 @@ export const VoidSelectBox = ({ onChangeSelection, initVal, selectBoxRef, option
|
|||
const defaultIndex = options.indexOf(initVal);
|
||||
|
||||
selectBoxRef.current = new SelectBox(
|
||||
options.map(opt => ({ text: opt })),
|
||||
options.map(opt => ({ text: opt, detail: 'detail', description: 'description' })),
|
||||
defaultIndex,
|
||||
contextViewProvider,
|
||||
unthemedSelectBoxStyles
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Glass Devtools, Inc. All rights reserved.
|
||||
* Void Editor additions licensed under the AGPLv3 License.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { diffLines, Change } from 'diff';
|
||||
|
||||
export { diffLines, Change }
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Glass Devtools, Inc. All rights reserved.
|
||||
* Void Editor additions licensed under the AGPLv3 License.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import * as ReactDOM from 'react-dom/client'
|
||||
import { ReactServicesType, VoidSidebarState } from '../../../registerSidebar.js';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,12 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Glass Devtools, Inc. All rights reserved.
|
||||
* Void Editor additions licensed under the AGPLv3 License.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { useState, useEffect } from 'react'
|
||||
import { VoidSidebarState, ReactServicesType } from '../../../registerSidebar.js'
|
||||
import { ThreadsState } from '../../../registerThreads.js'
|
||||
import { VoidProviderState } from '../../../../../../../platform/void/common/configTypes.js'
|
||||
import { SettingsOfProvider } from '../../../../../../../platform/void/common/voidConfigTypes.js'
|
||||
|
||||
|
||||
// normally to do this you'd use a useEffect that calls .onDidChangeState(), but useEffect mounts too late and misses initial state changes
|
||||
|
|
@ -10,13 +15,13 @@ let services: ReactServicesType
|
|||
|
||||
// even if React hasn't mounted yet, these variables are always updated to the latest state:
|
||||
let sidebarState: VoidSidebarState
|
||||
let configState: VoidProviderState
|
||||
let threadsState: ThreadsState
|
||||
let settingsOfProvider: SettingsOfProvider
|
||||
|
||||
// React listens by adding a setState function to these:
|
||||
const sidebarStateListeners: Set<(s: VoidSidebarState) => void> = new Set()
|
||||
const configStateListeners: Set<(s: VoidProviderState) => void> = new Set()
|
||||
const threadsStateListeners: Set<(s: ThreadsState) => void> = new Set()
|
||||
const settingsOfProviderListeners: Set<(s: SettingsOfProvider) => void> = new Set()
|
||||
|
||||
// must call this before you can use any of the hooks below
|
||||
// this should only be called ONCE! this is the only place you don't need to dispose onDidChange. If you use state.onDidChange anywhere else, make sure to dispose it!
|
||||
|
|
@ -25,7 +30,7 @@ let wasCalled = false
|
|||
|
||||
export const _registerServices = (services_: ReactServicesType) => {
|
||||
|
||||
if (wasCalled) console.error(`void _registerServices was called again! It should only be called once.`)
|
||||
if (wasCalled) console.error(`⚠️ Void _registerServices was called again! It should only be called once.`)
|
||||
wasCalled = true
|
||||
|
||||
services = services_
|
||||
|
|
@ -37,11 +42,6 @@ export const _registerServices = (services_: ReactServicesType) => {
|
|||
sidebarStateListeners.forEach(l => l(sidebarState))
|
||||
})
|
||||
|
||||
configState = configStateService.state
|
||||
configStateService.onDidChangeState(() => {
|
||||
configState = configStateService.state
|
||||
configStateListeners.forEach(l => l(configState))
|
||||
})
|
||||
|
||||
threadsState = threadsStateService.state
|
||||
threadsStateService.onDidChangeCurrentThread(() => {
|
||||
|
|
@ -49,15 +49,20 @@ export const _registerServices = (services_: ReactServicesType) => {
|
|||
threadsStateListeners.forEach(l => l(threadsState))
|
||||
})
|
||||
|
||||
settingsOfProvider = configStateService.state.settingsOfProvider
|
||||
configStateService.onDidChangeState(() => {
|
||||
settingsOfProvider = configStateService.state.settingsOfProvider
|
||||
settingsOfProviderListeners.forEach(l => l(settingsOfProvider))
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// -- services --
|
||||
export const useService = <T extends keyof ReactServicesType,>(serviceName: T) => {
|
||||
export const useService = <T extends keyof ReactServicesType,>(serviceName: T): ReactServicesType[T] => {
|
||||
if (services === null) {
|
||||
throw new Error('useAccessor must be used within an AccessorProvider')
|
||||
}
|
||||
return services[serviceName] as ReactServicesType[T]
|
||||
return services[serviceName]
|
||||
}
|
||||
|
||||
// -- state of services --
|
||||
|
|
@ -73,11 +78,11 @@ export const useSidebarState = () => {
|
|||
}
|
||||
|
||||
export const useConfigState = () => {
|
||||
const [s, ss] = useState(configState)
|
||||
const [s, ss] = useState(settingsOfProvider)
|
||||
useEffect(() => {
|
||||
ss(configState)
|
||||
configStateListeners.add(ss)
|
||||
return () => { configStateListeners.delete(ss) }
|
||||
ss(settingsOfProvider)
|
||||
settingsOfProviderListeners.add(ss)
|
||||
return () => { settingsOfProviderListeners.delete(ss) }
|
||||
}, [ss])
|
||||
return s
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import { ServicesAccessor } from '../../../../editor/browser/editorExtensions.js
|
|||
import { KeybindingWeight } from '../../../../platform/keybinding/common/keybindingsRegistry.js';
|
||||
import { ContextKeyExpr } from '../../../../platform/contextkey/common/contextkey.js';
|
||||
import { CodeStagingSelection, IThreadHistoryService } from './registerThreads.js';
|
||||
// import { IVoidConfigService } from './registerSettings.js';
|
||||
// import { IEditorService } from '../../../services/editor/common/editorService.js';
|
||||
|
||||
import { IEditorService } from '../../../services/editor/common/editorService.js';
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import { Disposable } from '../../../../base/common/lifecycle.js';
|
|||
import { ILanguageFeaturesService } from '../../../../editor/common/services/languageFeatures.js';
|
||||
import { registerSingleton, InstantiationType } from '../../../../platform/instantiation/common/extensions.js';
|
||||
import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';
|
||||
import { IVoidConfigStateService } from './registerConfig.js';
|
||||
import { ITextModel } from '../../../../editor/common/model.js';
|
||||
import { Position } from '../../../../editor/common/core/position.js';
|
||||
import { InlineCompletion, InlineCompletionContext } from '../../../../editor/common/languages.js';
|
||||
|
|
@ -516,7 +515,7 @@ export class AutocompleteService extends Disposable implements IAutocompleteServ
|
|||
const disabled = true
|
||||
const testMode = false
|
||||
|
||||
if (disabled) { return []; }
|
||||
if (disabled) return [];
|
||||
|
||||
const docUriStr = model.uri.toString();
|
||||
|
||||
|
|
@ -676,8 +675,8 @@ export class AutocompleteService extends Disposable implements IAutocompleteServ
|
|||
newAutocompletion.status = 'error'
|
||||
reject(error)
|
||||
},
|
||||
providerName: 'anthropic',
|
||||
voidConfig: this._voidConfigStateService.state,
|
||||
featureName: 'Autocomplete',
|
||||
range: { startLineNumber: position.lineNumber, startColumn: position.column, endLineNumber: position.lineNumber, endColumn: position.column },
|
||||
})
|
||||
newAutocompletion.requestId = requestId
|
||||
|
||||
|
|
@ -714,7 +713,6 @@ export class AutocompleteService extends Disposable implements IAutocompleteServ
|
|||
|
||||
constructor(
|
||||
@ILanguageFeaturesService private _langFeatureService: ILanguageFeaturesService,
|
||||
@IVoidConfigStateService private readonly _voidConfigStateService: IVoidConfigStateService,
|
||||
@ISendLLMMessageService private readonly _sendLLMMessageService: ISendLLMMessageService,
|
||||
@IEditorService private readonly _editorService: IEditorService,
|
||||
@IModelService private readonly _modelService: IModelService,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { ICodeEditor, IOverlayWidget, IViewZone } from '../../../../editor/brows
|
|||
// import { IUndoRedoService } from '../../../../platform/undoRedo/common/undoRedo.js';
|
||||
import { ICodeEditorService } from '../../../../editor/browser/services/codeEditorService.js';
|
||||
// import { throttle } from '../../../../base/common/decorators.js';
|
||||
import { IVoidConfigStateService } from './registerConfig.js';
|
||||
// import { IVoidConfigStateService } from './registerConfig.js';
|
||||
import { writeFileWithDiffInstructions } from './prompt/systemPrompts.js';
|
||||
import { ComputedDiff, findDiffs } from './findDiffs.js';
|
||||
import { EndOfLinePreference, ITextModel } from '../../../../editor/common/model.js';
|
||||
|
|
@ -28,9 +28,8 @@ import { ILanguageService } from '../../../../editor/common/languages/language.j
|
|||
import * as dom from '../../../../base/browser/dom.js';
|
||||
import { Widget } from '../../../../base/browser/ui/widget.js';
|
||||
import { URI } from '../../../../base/common/uri.js';
|
||||
import { LLMMessageServiceParams } from '../../../../platform/void/common/llmMessageTypes.js';
|
||||
import { LLMFeatureSelection, LLMMessageServiceParams } from '../../../../platform/void/common/llmMessageTypes.js';
|
||||
import { ISendLLMMessageService } from '../../../../platform/void/browser/llmMessageService.js';
|
||||
import { ProviderName } from '../../../../platform/void/common/configTypes.js';
|
||||
|
||||
|
||||
// gets converted to --vscode-void-greenBG, see void.css
|
||||
|
|
@ -104,25 +103,17 @@ type HistorySnapshot = {
|
|||
entireFileCode: string;
|
||||
} &
|
||||
({
|
||||
type: 'ctrl+k';
|
||||
type: 'Ctrl+K';
|
||||
ctrlKText: string;
|
||||
} | {
|
||||
type: 'ctrl+l';
|
||||
type: 'Ctrl+L';
|
||||
})
|
||||
|
||||
|
||||
type StartStreamingOptions = {
|
||||
type: 'ctrl+k',
|
||||
providerName: ProviderName,
|
||||
range: IRange
|
||||
} | {
|
||||
type: 'ctrl+l',
|
||||
providerName: ProviderName
|
||||
}
|
||||
|
||||
export interface IInlineDiffsService {
|
||||
readonly _serviceBrand: undefined;
|
||||
startStreaming(params: StartStreamingOptions, str: string): void;
|
||||
startStreaming(params: LLMFeatureSelection, str: string): void;
|
||||
}
|
||||
|
||||
export const IInlineDiffsService = createDecorator<IInlineDiffsService>('inlineDiffAreasService');
|
||||
|
|
@ -153,7 +144,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
|
||||
constructor(
|
||||
// @IHistoryService private readonly _historyService: IHistoryService, // history service is the history of pressing alt left/right
|
||||
@IVoidConfigStateService private readonly _voidConfigStateService: IVoidConfigStateService,
|
||||
// @IVoidConfigStateService private readonly _voidConfigStateService: IVoidConfigStateService,
|
||||
@ICodeEditorService private readonly _editorService: ICodeEditorService,
|
||||
@IModelService private readonly _modelService: IModelService,
|
||||
@IUndoRedoService private readonly _undoRedoService: IUndoRedoService, // undoRedo service is the history of pressing ctrl+z
|
||||
|
|
@ -379,7 +370,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
return {
|
||||
snapshottedDiffAreaOfId,
|
||||
entireFileCode: this._readURI(uri) ?? '', // the whole file's code
|
||||
type: 'ctrl+l',
|
||||
type: 'Ctrl+L',
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -646,7 +637,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
|
||||
|
||||
|
||||
private async _initializeStream(uri: URI, diffRepr: string, providerName: ProviderName) {
|
||||
private async _initializeStream(opts: LLMFeatureSelection, diffRepr: string, uri: URI,) {
|
||||
|
||||
// diff area begin and end line
|
||||
const numLines = this._getNumLines(uri)
|
||||
|
|
@ -698,7 +689,6 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
this.diffAreaOfId[diffArea.diffareaid] = diffArea
|
||||
|
||||
// actually call the LLM
|
||||
const voidConfigState = this._voidConfigStateService.state
|
||||
const promptContent = `\
|
||||
ORIGINAL_CODE
|
||||
\`\`\`
|
||||
|
|
@ -715,29 +705,6 @@ Please finish writing the new file by applying the diff to the original file. Re
|
|||
`
|
||||
|
||||
|
||||
// CTRL+K prompt:
|
||||
// const promptContent = `Here is the user's original selection:
|
||||
// \`\`\`
|
||||
// <MID>${selection}</MID>
|
||||
// \`\`\`
|
||||
|
||||
// The user wants to apply the following instructions to the selection:
|
||||
// ${instructions}
|
||||
|
||||
// Please rewrite the selection following the user's instructions.
|
||||
|
||||
// Instructions to follow:
|
||||
// 1. Follow the user's instructions
|
||||
// 2. You may ONLY CHANGE the selection, and nothing else in the file
|
||||
// 3. Make sure all brackets in the new selection are balanced the same was as in the original selection
|
||||
// 3. Be careful not to duplicate or remove variables, comments, or other syntax by mistake
|
||||
|
||||
// Complete the following:
|
||||
// \`\`\`
|
||||
// <PRE>${prefix}</PRE>
|
||||
// <SUF>${suffix}</SUF>
|
||||
// <MID>`;
|
||||
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
|
||||
let streamRequestId: string | null = null
|
||||
|
|
@ -770,8 +737,7 @@ Please finish writing the new file by applying the diff to the original file. Re
|
|||
diffArea._sweepState = { isStreaming: false, line: null }
|
||||
resolve();
|
||||
},
|
||||
voidConfig: voidConfigState,
|
||||
providerName,
|
||||
...opts
|
||||
}
|
||||
|
||||
streamRequestId = this._sendLLMMessageService.sendLLMMessage(object)
|
||||
|
|
@ -786,7 +752,7 @@ Please finish writing the new file by applying the diff to the original file. Re
|
|||
|
||||
|
||||
|
||||
async startStreaming(params: StartStreamingOptions, userMessage: string) {
|
||||
async startStreaming(opts: LLMFeatureSelection, userMessage: string) {
|
||||
|
||||
const editor = this._editorService.getActiveCodeEditor()
|
||||
if (!editor) return
|
||||
|
|
@ -798,7 +764,7 @@ Please finish writing the new file by applying the diff to the original file. Re
|
|||
|
||||
// TODO deselect user's cursor
|
||||
|
||||
this._initializeStream(uri, userMessage, params.providerName)
|
||||
this._initializeStream(opts, userMessage, uri)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ import { IHoverService } from '../../../../platform/hover/browser/hover.js';
|
|||
|
||||
import mountFn from './react/out/sidebar-tsx/Sidebar.js';
|
||||
|
||||
import { IVoidConfigStateService } from './registerConfig.js';
|
||||
import { IVoidConfigStateService } from '../../../../platform/void/common/voidConfigService.js';
|
||||
import { IFileService } from '../../../../platform/files/common/files.js';
|
||||
import { IInlineDiffsService } from './registerInlineDiffs.js';
|
||||
import { IModelService } from '../../../../editor/common/services/model.js';
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
import './registerActions.js'
|
||||
|
||||
// register Settings
|
||||
import './registerConfig.js' // TODO move this to platform
|
||||
import '../../../../platform/void/common/voidConfigService.js' // TODO move this to platform
|
||||
|
||||
// register inline diffs
|
||||
import './registerInlineDiffs.js'
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import './browser/workbench.contribution.js';
|
|||
// Void added this:
|
||||
import './contrib/void/browser/void.contribution.js';
|
||||
import '../platform/void/browser/llmMessageService.js';
|
||||
import '../platform/void/common/voidConfigService.js';
|
||||
//#endregion
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue