mirror of
https://github.com/voideditor/void
synced 2026-05-24 09:58:23 +00:00
feat: read .voidrules for system prompt
This commit is contained in:
parent
6d513a1e60
commit
9b130edcfe
6 changed files with 74 additions and 29 deletions
12
extensions/void/src/common/getRules.ts
Normal file
12
extensions/void/src/common/getRules.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import { awaitVSCodeResponse, getVSCodeAPI } from '../sidebar/getVscodeApi';
|
||||
|
||||
export async function getRules() {
|
||||
try {
|
||||
getVSCodeAPI().postMessage({ type: 'getRules', rules: '' })
|
||||
const rules = await awaitVSCodeResponse('getRules')
|
||||
return rules.rules
|
||||
} catch (error) {
|
||||
console.error('Error reading .voidrules file:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ import { createOpenAI, OpenAIProviderSettings } from '@ai-sdk/openai';
|
|||
import { AnthropicProviderSettings, createAnthropic } from '@ai-sdk/anthropic';
|
||||
import { AzureOpenAIProviderSettings, createAzure } from '@ai-sdk/azure';
|
||||
import { createOllama, OllamaProviderSettings } from 'ollama-ai-provider';
|
||||
import { getRules } from './getRules';
|
||||
|
||||
export type ApiConfig = {
|
||||
/** @default 'anthropic' */
|
||||
|
|
@ -142,24 +143,29 @@ const sendGreptileMsg: SendLLMMessageFnTypeInternal = ({ messages, onText, onFin
|
|||
export const sendLLMMessage: SendLLMMessageFnTypeExternal = ({ messages, onText, onFinalMessage, apiConfig }) => {
|
||||
if (!apiConfig) return { abort: () => { } }
|
||||
const provider = apiConfig.provider
|
||||
// TODO: create an @ai-sdk provider for greptile
|
||||
// TODO: create an @ai-sdk provider for greptile,
|
||||
if (provider === 'greptile')
|
||||
return sendGreptileMsg({ messages, onText, onFinalMessage, apiConfig })
|
||||
|
||||
const model = getAiModel(apiConfig)
|
||||
|
||||
const abortController = new AbortController()
|
||||
const abortSignal = abortController.signal
|
||||
streamText({
|
||||
model,
|
||||
messages,
|
||||
abortSignal,
|
||||
}).then(async (result) => {
|
||||
let fullText = ''
|
||||
for await (const textPart of result.textStream) {
|
||||
fullText += textPart
|
||||
onText(textPart, fullText)
|
||||
}
|
||||
onFinalMessage(fullText)
|
||||
|
||||
getRules().then(rules => {
|
||||
streamText({
|
||||
model,
|
||||
system: rules || '',
|
||||
messages,
|
||||
abortSignal,
|
||||
}).then(async (result) => {
|
||||
let fullText = ''
|
||||
for await (const textPart of result.textStream) {
|
||||
fullText += textPart
|
||||
onText(textPart, fullText)
|
||||
}
|
||||
onFinalMessage(fullText)
|
||||
})
|
||||
})
|
||||
|
||||
return { abort: abortController.abort }
|
||||
|
|
@ -167,20 +173,28 @@ export const sendLLMMessage: SendLLMMessageFnTypeExternal = ({ messages, onText,
|
|||
|
||||
export const getAiModel = (apiConfig: ApiConfig) => {
|
||||
switch (apiConfig.provider) {
|
||||
case 'openai': return createOpenAI({
|
||||
...apiConfig.openai.providerSettings,
|
||||
apiKey: apiConfig.openai.apiKey,
|
||||
})(apiConfig.openai.model || 'gpt-4o')
|
||||
case 'anthropic': return createAnthropic({
|
||||
...apiConfig.anthropic.providerSettings,
|
||||
apiKey: apiConfig.anthropic.apiKey,
|
||||
})(apiConfig.anthropic.model || 'claude-3-5-sonnet-20240620')
|
||||
case 'ollama': return createOllama(apiConfig.ollama.providerSettings)(apiConfig.ollama.model || 'llama3.1')
|
||||
case 'azure': return createAzure({
|
||||
...apiConfig.azure.providerSettings,
|
||||
apiKey: apiConfig.azure.apiKey,
|
||||
resourceName: apiConfig.azure.resourceName,
|
||||
})(`${apiConfig.azure.deploymentId}`)
|
||||
case 'openai':
|
||||
return createOpenAI({
|
||||
...apiConfig.openai.providerSettings,
|
||||
apiKey: apiConfig.openai.apiKey,
|
||||
})(apiConfig.openai.model || 'gpt-4o')
|
||||
|
||||
case 'anthropic':
|
||||
return createAnthropic({
|
||||
...apiConfig.anthropic.providerSettings,
|
||||
apiKey: apiConfig.anthropic.apiKey,
|
||||
})(apiConfig.anthropic.model || 'claude-3-5-sonnet-20240620')
|
||||
|
||||
case 'ollama':
|
||||
return createOllama(apiConfig.ollama.providerSettings)(apiConfig.ollama.model || 'llama3.1')
|
||||
|
||||
case 'azure':
|
||||
return createAzure({
|
||||
...apiConfig.azure.providerSettings,
|
||||
apiKey: apiConfig.azure.apiKey,
|
||||
resourceName: apiConfig.azure.resourceName,
|
||||
})(`${apiConfig.azure.deploymentId}`)
|
||||
|
||||
default:
|
||||
throw new Error(`Error: provider was ${apiConfig.provider}, which is not recognized!`)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,7 +115,22 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
// Receive messages in the extension from the sidebar webview (messages are sent using `postMessage`)
|
||||
webview.onDidReceiveMessage(async (m: WebviewMessage) => {
|
||||
|
||||
if (m.type === 'requestFiles') {
|
||||
if (m.type === 'getRules') {
|
||||
const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
|
||||
if (workspaceFolder) {
|
||||
const rulesFilePath = vscode.Uri.joinPath(workspaceFolder.uri, '.voidrules');
|
||||
try {
|
||||
const rulesContent = await readFileContentOfUri(rulesFilePath);
|
||||
webview.postMessage({ type: 'getRules', rules: rulesContent } satisfies WebviewMessage);
|
||||
} catch (error) {
|
||||
console.error('Error reading .voidrules file:', error);
|
||||
webview.postMessage({ type: 'getRules', rules: null } satisfies WebviewMessage);
|
||||
}
|
||||
} else {
|
||||
webview.postMessage({ type: 'getRules', rules: null } satisfies WebviewMessage);
|
||||
}
|
||||
}
|
||||
else if (m.type === 'requestFiles') {
|
||||
|
||||
// get contents of all file paths
|
||||
const files = await Promise.all(
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ type WebviewMessage = (
|
|||
// editor -> sidebar
|
||||
| { type: 'apiConfig', apiConfig: ApiConfig }
|
||||
|
||||
// sidebar -> editor
|
||||
| { type: 'getRules', rules: string | null }
|
||||
|
||||
)
|
||||
|
||||
type Command = WebviewMessage['type']
|
||||
|
|
|
|||
|
|
@ -266,7 +266,7 @@ const Sidebar = () => {
|
|||
{!selection?.selectionStr ? null
|
||||
: (
|
||||
<div className="relative">
|
||||
<button
|
||||
<button
|
||||
onClick={clearSelection}
|
||||
className="absolute top-2 right-2 text-white hover:text-gray-300 z-10"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ const awaiting: { [c in Command]: ((res: any) => void)[] } = {
|
|||
"requestFiles": [],
|
||||
"files": [],
|
||||
"apiConfig": [],
|
||||
"getApiConfig": []
|
||||
"getApiConfig": [],
|
||||
"getRules": []
|
||||
}
|
||||
|
||||
// use this function to await responses
|
||||
|
|
|
|||
Loading…
Reference in a new issue