mirror of
https://github.com/voideditor/void
synced 2026-05-24 09:58:23 +00:00
llmMessageService now multiplexes between sendLLMMessage, ollama, etc
This commit is contained in:
parent
94f4d2caaf
commit
1365400f21
8 changed files with 47 additions and 67 deletions
|
|
@ -15,18 +15,18 @@ import { IVoidConfigStateService } from '../common/voidConfigService.js';
|
|||
// import { INotificationService } from '../../notification/common/notification.js';
|
||||
|
||||
|
||||
// BROWSER IMPLEMENTATION OF SENDLLMMESSAGE
|
||||
export const ISendLLMMessageService = createDecorator<ISendLLMMessageService>('sendLLMMessageService');
|
||||
// BROWSER IMPLEMENTATION
|
||||
export const ILLMMessageService = createDecorator<ILLMMessageService>('llmMessageService');
|
||||
|
||||
// defines an interface that node/ creates and browser/ uses
|
||||
export interface ISendLLMMessageService {
|
||||
export interface ILLMMessageService {
|
||||
readonly _serviceBrand: undefined;
|
||||
sendLLMMessage: (params: ServiceSendLLMMessageParams) => string | null;
|
||||
abort: (requestId: string) => void;
|
||||
}
|
||||
|
||||
|
||||
export class SendLLMMessageService extends Disposable implements ISendLLMMessageService {
|
||||
export class LLMMessageService extends Disposable implements ILLMMessageService {
|
||||
|
||||
readonly _serviceBrand: undefined;
|
||||
private readonly channel: IChannel // LLMMessageChannel
|
||||
|
|
@ -53,30 +53,27 @@ export class SendLLMMessageService extends Disposable implements ISendLLMMessage
|
|||
this.channel = this.mainProcessService.getChannel('void-channel-llmMessageService')
|
||||
|
||||
// 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<EventLLMMessageOnTextParams> = this.channel.listen('onText')
|
||||
const onFinalMessageEvent: Event<EventLLMMessageOnFinalMessageParams> = this.channel.listen('onFinalMessage')
|
||||
const onErrorEvent: Event<EventLLMMessageOnErrorParams> = this.channel.listen('onError')
|
||||
|
||||
this._register(
|
||||
onTextEvent(e => {
|
||||
this.onTextHooks_llm[e.requestId]?.(e)
|
||||
})
|
||||
)
|
||||
|
||||
this._register(
|
||||
onFinalMessageEvent(e => {
|
||||
this.onFinalMessageHooks_llm[e.requestId]?.(e)
|
||||
this._onRequestIdDone(e.requestId)
|
||||
})
|
||||
)
|
||||
|
||||
this._register(
|
||||
onErrorEvent(e => {
|
||||
console.log('Error in SendLLMMessageService:', JSON.stringify(e))
|
||||
this.onErrorHooks_llm[e.requestId]?.(e)
|
||||
this._onRequestIdDone(e.requestId)
|
||||
})
|
||||
)
|
||||
// llm
|
||||
this._register((this.channel.listen('onText_llm') satisfies Event<EventLLMMessageOnTextParams>)(e => {
|
||||
this.onTextHooks_llm[e.requestId]?.(e)
|
||||
}))
|
||||
this._register((this.channel.listen('onFinalMessage_llm') satisfies Event<EventLLMMessageOnFinalMessageParams>)(e => {
|
||||
this.onFinalMessageHooks_llm[e.requestId]?.(e)
|
||||
this._onRequestIdDone(e.requestId)
|
||||
}))
|
||||
this._register((this.channel.listen('onError_llm') satisfies Event<EventLLMMessageOnErrorParams>)(e => {
|
||||
console.log('Error in LLMMessageService:', JSON.stringify(e))
|
||||
this.onErrorHooks_llm[e.requestId]?.(e)
|
||||
this._onRequestIdDone(e.requestId)
|
||||
}))
|
||||
// ollama
|
||||
this._register((this.channel.listen('onSuccess_ollama') satisfies Event<EventOllamaListOnSuccessParams>)(e => {
|
||||
this.onSuccess_ollama[e.requestId]?.(e)
|
||||
}))
|
||||
this._register((this.channel.listen('onError_ollama') satisfies Event<EventOllamaListOnErrorParams>)(e => {
|
||||
this.onError_ollama[e.requestId]?.(e)
|
||||
}))
|
||||
}
|
||||
|
||||
sendLLMMessage(params: ServiceSendLLMMessageParams) {
|
||||
|
|
@ -145,5 +142,5 @@ export class SendLLMMessageService extends Disposable implements ISendLLMMessage
|
|||
}
|
||||
}
|
||||
|
||||
registerSingleton(ISendLLMMessageService, SendLLMMessageService, InstantiationType.Delayed);
|
||||
registerSingleton(ILLMMessageService, LLMMessageService, InstantiationType.Delayed);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,6 @@
|
|||
// metrics
|
||||
import '../browser/metricsService.js'
|
||||
|
||||
// ollamaList
|
||||
import '../browser/ollamaListService.js'
|
||||
|
||||
// --- common ---
|
||||
// llmMessage
|
||||
import '../browser/llmMessageService.js'
|
||||
|
|
|
|||
|
|
@ -18,22 +18,15 @@ import { ollamaList } from './llmMessage/ollama.js';
|
|||
export class LLMMessageChannel implements IServerChannel {
|
||||
// sendLLMMessage
|
||||
private readonly _onText_llm = new Emitter<EventLLMMessageOnTextParams>();
|
||||
private readonly onText_llm = this._onText_llm.event;
|
||||
|
||||
private readonly _onFinalMessage_llm = new Emitter<EventLLMMessageOnFinalMessageParams>();
|
||||
private readonly onFinalMessage_llm = this._onFinalMessage_llm.event;
|
||||
|
||||
private readonly _onError_llm = new Emitter<EventLLMMessageOnErrorParams>();
|
||||
private readonly onError_llm = this._onError_llm.event;
|
||||
|
||||
// abort
|
||||
private readonly _abortRefOfRequestId_llm: Record<string, AbortRef> = {}
|
||||
|
||||
// ollamaList
|
||||
private readonly _onSuccess_ollama = new Emitter<EventOllamaListOnSuccessParams>();
|
||||
private readonly onSuccess_ollama = this._onSuccess_ollama.event;
|
||||
|
||||
private readonly _onError_ollama = new Emitter<EventOllamaListOnErrorParams>();
|
||||
private readonly onError_ollama = this._onError_ollama.event;
|
||||
|
||||
// stupidly, channels can't take in @IService
|
||||
constructor(
|
||||
|
|
@ -44,19 +37,19 @@ export class LLMMessageChannel implements IServerChannel {
|
|||
// browser uses this to listen for changes
|
||||
listen(_: unknown, event: string): Event<any> {
|
||||
if (event === 'onText_llm') {
|
||||
return this.onText_llm;
|
||||
return this._onText_llm.event;
|
||||
}
|
||||
else if (event === 'onFinalMessage_llm') {
|
||||
return this.onFinalMessage_llm;
|
||||
return this._onFinalMessage_llm.event;
|
||||
}
|
||||
else if (event === 'onError_llm') {
|
||||
return this.onError_llm;
|
||||
return this._onError_llm.event;
|
||||
}
|
||||
else if (event === 'onSuccess_ollama') {
|
||||
return this.onSuccess_ollama;
|
||||
return this._onSuccess_ollama.event;
|
||||
}
|
||||
else if (event === 'onError_ollama') {
|
||||
return this.onError_ollama;
|
||||
return this._onError_ollama.event;
|
||||
}
|
||||
else {
|
||||
throw new Error(`Event not found: ${event}`);
|
||||
|
|
@ -65,7 +58,6 @@ export class LLMMessageChannel implements IServerChannel {
|
|||
|
||||
// browser uses this to call
|
||||
async call(_: unknown, command: string, params: any): Promise<any> {
|
||||
|
||||
try {
|
||||
if (command === 'sendLLMMessage') {
|
||||
this._callSendLLMMessage(params)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import { URI } from '../../../../../../../base/common/uri.js';
|
|||
import { EndOfLinePreference } from '../../../../../../../editor/common/model.js';
|
||||
import { IDisposable } from '../../../../../../../base/common/lifecycle.js';
|
||||
import { ErrorDisplay } from './ErrorDisplay.js';
|
||||
import { LLMMessageServiceParams, OnError } from '../../../../../../../platform/void/common/llmMessageTypes.js';
|
||||
import { OnError, ServiceSendLLMMessageParams } from '../../../../../../../platform/void/common/llmMessageTypes.js';
|
||||
import { getCmdKey } from '../../../getCmdKey.js'
|
||||
import { HistoryInputBox, InputBox } from '../../../../../../../base/browser/ui/inputbox/inputBox.js';
|
||||
import { VoidInputBox } from './inputs.js';
|
||||
|
|
@ -240,7 +240,7 @@ export const SidebarChat = () => {
|
|||
|
||||
const [latestError, setLatestError] = useState<Parameters<OnError>[0] | null>(null)
|
||||
|
||||
const sendLLMMessageService = useService('sendLLMMessageService')
|
||||
const llmMessageService = useService('llmMessageService')
|
||||
|
||||
// state of current message
|
||||
const [instructions, setInstructions] = useState('') // the user's instructions
|
||||
|
|
@ -295,7 +295,7 @@ export const SidebarChat = () => {
|
|||
inputBoxRef.current.blur();
|
||||
}
|
||||
|
||||
const object: LLMMessageServiceParams = {
|
||||
const object: ServiceSendLLMMessageParams = {
|
||||
logging: { loggingName: 'Chat' },
|
||||
messages: [...(currentThread?.messages ?? []).map(m => ({ role: m.role, content: m.content || '(null)' })),],
|
||||
onText: ({ newText, fullText }) => setMessageStream(fullText),
|
||||
|
|
@ -325,7 +325,7 @@ export const SidebarChat = () => {
|
|||
|
||||
}
|
||||
|
||||
const latestRequestId = sendLLMMessageService.sendLLMMessage(object)
|
||||
const latestRequestId = llmMessageService.sendLLMMessage(object)
|
||||
latestRequestIdRef.current = latestRequestId
|
||||
|
||||
threadsStateService.setStaging([]) // clear staging
|
||||
|
|
@ -335,7 +335,7 @@ export const SidebarChat = () => {
|
|||
const onAbort = () => {
|
||||
// abort the LLM call
|
||||
if (latestRequestIdRef.current)
|
||||
sendLLMMessageService.abort(latestRequestIdRef.current)
|
||||
llmMessageService.abort(latestRequestIdRef.current)
|
||||
|
||||
// if messageStream was not empty, add it to the history
|
||||
const llmContent = messageStream ?? ''
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import { Position } from '../../../../editor/common/core/position.js';
|
|||
import { InlineCompletion, InlineCompletionContext } from '../../../../editor/common/languages.js';
|
||||
import { CancellationToken } from '../../../../base/common/cancellation.js';
|
||||
import { Range } from '../../../../editor/common/core/range.js';
|
||||
import { ISendLLMMessageService } from '../../../../platform/void/browser/llmMessageService.js';
|
||||
import { ILLMMessageService } from '../../../../platform/void/browser/llmMessageService.js';
|
||||
import { IEditorService } from '../../../services/editor/common/editorService.js';
|
||||
import { isCodeEditor } from '../../../../editor/browser/editorBrowser.js';
|
||||
import { EditorResourceAccessor } from '../../../common/editor.js';
|
||||
|
|
@ -527,7 +527,7 @@ export class AutocompleteService extends Disposable implements IAutocompleteServ
|
|||
MAX_CACHE_SIZE,
|
||||
(autocompletion: Autocompletion) => {
|
||||
if (autocompletion.requestId)
|
||||
this._sendLLMMessageService.abort(autocompletion.requestId)
|
||||
this._llmMessageService.abort(autocompletion.requestId)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -644,7 +644,7 @@ export class AutocompleteService extends Disposable implements IAutocompleteServ
|
|||
// set parameters of `newAutocompletion` appropriately
|
||||
newAutocompletion.llmPromise = new Promise((resolve, reject) => {
|
||||
|
||||
const requestId = this._sendLLMMessageService.sendLLMMessage({
|
||||
const requestId = this._llmMessageService.sendLLMMessage({
|
||||
logging: { loggingName: 'Autocomplete' },
|
||||
messages: [],
|
||||
onText: async ({ newText, fullText }) => {
|
||||
|
|
@ -713,7 +713,7 @@ export class AutocompleteService extends Disposable implements IAutocompleteServ
|
|||
|
||||
constructor(
|
||||
@ILanguageFeaturesService private _langFeatureService: ILanguageFeaturesService,
|
||||
@ISendLLMMessageService private readonly _sendLLMMessageService: ISendLLMMessageService,
|
||||
@ILLMMessageService private readonly _llmMessageService: ILLMMessageService,
|
||||
@IEditorService private readonly _editorService: IEditorService,
|
||||
@IModelService private readonly _modelService: IModelService,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ import * as dom from '../../../../base/browser/dom.js';
|
|||
import { Widget } from '../../../../base/browser/ui/widget.js';
|
||||
import { URI } from '../../../../base/common/uri.js';
|
||||
import { LLMFeatureSelection, ServiceSendLLMMessageParams } from '../../../../platform/void/common/llmMessageTypes.js';
|
||||
import { ISendLLMMessageService } from '../../../../platform/void/browser/llmMessageService.js';
|
||||
import { ILLMMessageService } from '../../../../platform/void/browser/llmMessageService.js';
|
||||
|
||||
|
||||
// gets converted to --vscode-void-greenBG, see void.css
|
||||
|
|
@ -149,7 +149,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
@IModelService private readonly _modelService: IModelService,
|
||||
@IUndoRedoService private readonly _undoRedoService: IUndoRedoService, // undoRedo service is the history of pressing ctrl+z
|
||||
@ILanguageService private readonly _langService: ILanguageService,
|
||||
@ISendLLMMessageService private readonly _sendLLMMessageService: ISendLLMMessageService,
|
||||
@ILLMMessageService private readonly _llmMessageService: ILLMMessageService,
|
||||
) {
|
||||
super();
|
||||
|
||||
|
|
@ -732,7 +732,7 @@ Please finish writing the new file by applying the diff to the original file. Re
|
|||
console.error('Error rewriting file with diff', e);
|
||||
// TODO indicate there was an error
|
||||
if (streamRequestId)
|
||||
this._sendLLMMessageService.abort(streamRequestId)
|
||||
this._llmMessageService.abort(streamRequestId)
|
||||
|
||||
diffArea._sweepState = { isStreaming: false, line: null }
|
||||
resolve();
|
||||
|
|
@ -740,7 +740,7 @@ Please finish writing the new file by applying the diff to the original file. Re
|
|||
...opts
|
||||
}
|
||||
|
||||
streamRequestId = this._sendLLMMessageService.sendLLMMessage(object)
|
||||
streamRequestId = this._llmMessageService.sendLLMMessage(object)
|
||||
})
|
||||
|
||||
onFinishEdit()
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ import { IVoidConfigStateService } from '../../../../platform/void/common/voidCo
|
|||
import { IFileService } from '../../../../platform/files/common/files.js';
|
||||
import { IInlineDiffsService } from './registerInlineDiffs.js';
|
||||
import { IModelService } from '../../../../editor/common/services/model.js';
|
||||
import { ISendLLMMessageService } from '../../../../platform/void/browser/llmMessageService.js';
|
||||
import { ILLMMessageService } from '../../../../platform/void/browser/llmMessageService.js';
|
||||
import { IClipboardService } from '../../../../platform/clipboard/common/clipboardService.js';
|
||||
import { IViewsService } from '../../../services/views/common/viewsService.js';
|
||||
import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';
|
||||
|
|
@ -62,7 +62,7 @@ export type ReactServicesType = {
|
|||
fileService: IFileService;
|
||||
modelService: IModelService;
|
||||
inlineDiffService: IInlineDiffsService;
|
||||
sendLLMMessageService: ISendLLMMessageService;
|
||||
llmMessageService: ILLMMessageService;
|
||||
clipboardService: IClipboardService;
|
||||
|
||||
themeService: IThemeService,
|
||||
|
|
@ -109,7 +109,7 @@ class VoidSidebarViewPane extends ViewPane {
|
|||
fileService: accessor.get(IFileService),
|
||||
modelService: accessor.get(IModelService),
|
||||
inlineDiffService: accessor.get(IInlineDiffsService),
|
||||
sendLLMMessageService: accessor.get(ISendLLMMessageService),
|
||||
llmMessageService: accessor.get(ILLMMessageService),
|
||||
clipboardService: accessor.get(IClipboardService),
|
||||
themeService: accessor.get(IThemeService),
|
||||
hoverService: accessor.get(IHoverService),
|
||||
|
|
|
|||
|
|
@ -31,12 +31,6 @@ import './electron-sandbox/parts/dialogs/dialog.contribution.js';
|
|||
|
||||
//#endregion
|
||||
|
||||
// //#region --- Void
|
||||
// // Void added this (modeling off of import '.*clipboardservice.js'):
|
||||
// import './services/void/electron-main/sendLLMMessage.js';
|
||||
// //#endregion
|
||||
|
||||
|
||||
|
||||
//#region --- workbench services
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue