diff --git a/.gitignore b/.gitignore index fcdb9b6f..5daf304c 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,3 @@ product.overrides.json *.snap.actual .vscode-test .tmp/ -.tool-versions diff --git a/src/package-lock.json b/src/package-lock.json deleted file mode 100644 index 3b02711d..00000000 --- a/src/package-lock.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "name": "src", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "dependencies": { - "@mistralai/mistralai": "^1.3.5", - "zod": "^3.23.8" - } - }, - "node_modules/@mistralai/mistralai": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@mistralai/mistralai/-/mistralai-1.3.5.tgz", - "integrity": "sha512-yC91oJ5ScEPqbXmv3mJTwTFgu/ZtsYoOPOhaVXSsy6x4zXTqTI57yEC1flC9uiA8GpG/yhpn2BBUXF95+U9Blw==", - "peerDependencies": { - "react": "^18 || ^19", - "react-dom": "^18 || ^19", - "zod": ">= 3" - } - }, - "node_modules/react": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", - "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz", - "integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "scheduler": "^0.25.0" - }, - "peerDependencies": { - "react": "^19.0.0" - } - }, - "node_modules/scheduler": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz", - "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==", - "license": "MIT", - "peer": true - }, - "node_modules/zod": { - "version": "3.23.8", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", - "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - } - } -} diff --git a/src/vs/platform/void/common/voidSettingsService.ts b/src/vs/platform/void/common/voidSettingsService.ts index 7200d8bf..4030a3f3 100644 --- a/src/vs/platform/void/common/voidSettingsService.ts +++ b/src/vs/platform/void/common/voidSettingsService.ts @@ -117,9 +117,9 @@ class VoidSettingsService extends Disposable implements IVoidSettingsService { // read and update the actual state immediately this._readState().then(readS => { - // THIS IS A HACK BECAUSE WE ADDED DEEPSEEK - const deepseekAdd = { deepseek: defaultSettingsOfProvider['deepseek'] } - readS = { ...readS, settingsOfProvider: { ...deepseekAdd, ...readS.settingsOfProvider, } } + // THIS IS A HACK BECAUSE WE ADDED DEEPSEEK AND MISTRAL + const additions = { deepseek: defaultSettingsOfProvider['deepseek'], mistral: defaultSettingsOfProvider['mistral'] } + readS = { ...readS, settingsOfProvider: { ...additions, ...readS.settingsOfProvider, } } this.state = readS resolver() diff --git a/src/vs/platform/void/common/voidSettingsTypes.ts b/src/vs/platform/void/common/voidSettingsTypes.ts index 709bc8e0..458d6a16 100644 --- a/src/vs/platform/void/common/voidSettingsTypes.ts +++ b/src/vs/platform/void/common/voidSettingsTypes.ts @@ -363,16 +363,16 @@ export const voidInitModelOptions = { // used when waiting and for a type reference export const defaultSettingsOfProvider: SettingsOfProvider = { anthropic: { - _enabled: undefined, ...defaultCustomSettings, ...defaultProviderSettings.anthropic, ...voidInitModelOptions.anthropic, + _enabled: undefined, }, openAI: { - _enabled: undefined, ...defaultCustomSettings, ...defaultProviderSettings.openAI, ...voidInitModelOptions.openAI, + _enabled: undefined, }, deepseek: { ...defaultCustomSettings, diff --git a/src/vs/platform/void/electron-main/llmMessage/groq.ts b/src/vs/platform/void/electron-main/llmMessage/groq.ts index 1050e25c..70a4250b 100644 --- a/src/vs/platform/void/electron-main/llmMessage/groq.ts +++ b/src/vs/platform/void/electron-main/llmMessage/groq.ts @@ -22,7 +22,7 @@ export const sendGroqMsg: _InternalSendLLMMessageFnType = async ({ messages, onT messages: messages, model: modelName, stream: true, - temperature: 0.7, + // temperature: 0.7, // max_tokens: parseMaxTokensStr(thisConfig.maxTokens), }) .then(async response => { @@ -30,10 +30,8 @@ export const sendGroqMsg: _InternalSendLLMMessageFnType = async ({ messages, onT // when receive text for await (const chunk of response) { const newText = chunk.choices[0]?.delta?.content || ''; - if (newText) { - fullText += newText; - onText({ newText, fullText }); - } + fullText += newText; + onText({ newText, fullText }); } onFinalMessage({ fullText }); diff --git a/src/vs/platform/void/electron-main/llmMessage/mistral.ts b/src/vs/platform/void/electron-main/llmMessage/mistral.ts index bf991b22..74f9233e 100644 --- a/src/vs/platform/void/electron-main/llmMessage/mistral.ts +++ b/src/vs/platform/void/electron-main/llmMessage/mistral.ts @@ -1,122 +1,46 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Glass Devtools, Inc. All rights reserved. - * Mistral implementation by Jérôme Commaret (https://github.com/jcommaret) - * Void Editor additions licensed under the AGPL 3.0 License. - *--------------------------------------------------------------------------------------------*/ +/*-------------------------------------------------------------------------------------- + * Copyright 2025 Glass Devtools, Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information. + *--------------------------------------------------------------------------------------*/ import { Mistral } from '@mistralai/mistralai'; import { _InternalSendLLMMessageFnType } from '../../common/llmMessageTypes.js'; -interface MistralMessage { - role: 'user' | 'assistant'; - content: string; -} - -interface MistralChunk { - data: { - id: string; - object: string; - created: number; - model: string; - choices: Array<{ - index: number; - delta: { - content?: string; - role?: string; - }; - finishReason: string | null; - }>; - }; -} - // Mistral export const sendMistralMsg: _InternalSendLLMMessageFnType = async ({ messages, onText, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter }) => { let fullText = ''; - let aborted = false; const thisConfig = settingsOfProvider.mistral; - if (!thisConfig.apiKey) { - onError({ message: 'Mistral API key not configured.', fullError: new Error('No API key') }); - return; - } - const mistral = new Mistral({ - apiKey: thisConfig.apiKey - }); + apiKey: thisConfig.apiKey, + }) - // Define the aborter before staring the stream - _setAborter(() => { - aborted = true; - }); - - try { - // Check if there are messages to process - if (!messages || messages.length === 0) { - onError({ message: 'No messages to process.', fullError: new Error('No messages provided') }); - return; - } - - // Convert messages for Mistral - const mistralMessages = messages - .map(msg => ({ - role: msg.role === 'assistant' ? 'assistant' : 'user', - content: msg.content.trim() - })) as MistralMessage[]; - - // Ensure there is at least one message - if (mistralMessages.length === 0) { - onError({ message: 'No valid messages to send.', fullError: new Error('No valid messages') }); - return; - } - - // Ensure the last message is from the user - if (mistralMessages[mistralMessages.length - 1].role === 'assistant') { - mistralMessages.push({ - role: 'user', - content: 'Continue.' - }); - } - - const stream = await mistral.chat.stream({ + await mistral.chat + .stream({ + messages: messages, model: modelName, - messages: mistralMessages, - temperature: 0.7, - maxTokens: 2048 - }); - - for await (const chunk of stream) { - // Check if the request has been aborted - if (aborted) { - return; + stream: true, + // temperature: 0.7, + // maxTokens: 2048, + }) + .then(async response => { + // Mistral has a really nonstandard API - no interrupt and weird stream types + _setAborter(() => { console.log('Mistral does not support interrupts! Further messages will just be ignored.') }); + // when receive text + for await (const chunk of response) { + const c = chunk.data.choices[0].delta.content || '' + const newText = ( + typeof c === 'string' ? c + : c?.map(c => c.type === 'text' ? c.text : c.type).join('\n') + ) + fullText += newText; + onText({ newText, fullText }); } - if (typeof chunk === 'object' && chunk && 'data' in chunk) { - const { data } = chunk as MistralChunk; - if (data.choices?.[0]?.delta?.content) { - const newText = data.choices[0].delta.content; - fullText += newText; - onText({ newText, fullText }); - } - } - } - - // Check one last time if the request has been aborted - if (aborted) { - return; - } - - if (!fullText) { - onError({ message: 'No response received from Mistral.', fullError: new Error('No response content') }); - return; - } - - onFinalMessage({ fullText }); - } catch (error: any) { - const errorMessage = error.message || JSON.stringify(error); - onError({ - message: `Mistral Error: ${errorMessage}`, - fullError: error - }); - } -}; + onFinalMessage({ fullText }); + }) + .catch(error => { + onError({ message: error + '', fullError: error }); + }) +} diff --git a/void b/void deleted file mode 160000 index 5083b8e9..00000000 --- a/void +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5083b8e971e48ae1001e5c8ceee7b010bcea3640