feat: read .voidrules for system prompt

This commit is contained in:
Jelf 2024-09-22 17:35:51 +08:00
parent 6d513a1e60
commit 9b130edcfe
6 changed files with 74 additions and 29 deletions

View 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;
}
}

View file

@ -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!`)
}

View file

@ -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(

View file

@ -27,6 +27,9 @@ type WebviewMessage = (
// editor -> sidebar
| { type: 'apiConfig', apiConfig: ApiConfig }
// sidebar -> editor
| { type: 'getRules', rules: string | null }
)
type Command = WebviewMessage['type']

View file

@ -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"
>

View file

@ -9,7 +9,8 @@ const awaiting: { [c in Command]: ((res: any) => void)[] } = {
"requestFiles": [],
"files": [],
"apiConfig": [],
"getApiConfig": []
"getApiConfig": [],
"getRules": []
}
// use this function to await responses