diff --git a/extensions/void/package.json b/extensions/void/package.json index 5db043eb..63981439 100644 --- a/extensions/void/package.json +++ b/extensions/void/package.json @@ -1,5 +1,6 @@ { "name": "void", + "publisher": "void", "displayName": "Void", "description": "", "version": "0.0.1", @@ -13,28 +14,30 @@ "main": "./out/extension.js", "contributes": { "configuration": { - "title": "API Keys", + "title": "Void", "properties": { "void.provider": { "type": "string", "default": "anthropic", - "description": "Choose a provider (openai | anthropic | azure | greptile | ollama)", + "description": "Choose an API provider.", "enum": [ - "openai", + "openAI", + "openAICompatible", "anthropic", "azure", - "greptile", - "ollama" + "ollama", + "greptile" ] }, "void.anthropic.apiKey": { "type": "string", + "default": "", "description": "Anthropic API key." }, "void.anthropic.model": { "type": "string", "default": "claude-3-5-sonnet-20240620", - "description": "Choose a model ('claude-3-5-sonnet-20240620' | 'claude-3-opus-20240229' | 'claude-3-sonnet-20240229' | 'claude-3-haiku-20240307')", + "description": "Anthropic model to use.", "enum": [ "claude-3-5-sonnet-20240620", "claude-3-opus-20240229", @@ -42,27 +45,26 @@ "claude-3-haiku-20240307" ] }, - "void.anthropic.providerSettings": { - "type": "object", - "properties": { - "baseURL": { - "type": "string", - "description": "Use a different URL prefix for API calls, e.g. to use proxy servers." - }, - "headers": { - "type": "object", - "description": "Custom headers to include in the requests." - } - } - }, - "void.openai.apiKey": { + "void.anthropic.maxTokens": { "type": "string", + "default": "8192", + "description": "Anthropic max number of tokens to output.", + "enum": [ + "1024", + "2048", + "4096", + "8192" + ] + }, + "void.openAI.apiKey": { + "type": "string", + "default": "", "description": "OpenAI API key." }, - "void.openai.model": { + "void.openAI.model": { "type": "string", "default": "gpt-4o", - "description": "Choose a model ('o1-preview' | 'o1-mini' | 'gpt-4o' | 'gpt-4o-2024-05-13' | 'gpt-4o-2024-08-06' | 'gpt-4o-mini' | 'gpt-4o-mini-2024-07-18' | 'gpt-4-turbo' | 'gpt-4-turbo-2024-04-09' | 'gpt-4-turbo-preview' | 'gpt-4-0125-preview' | 'gpt-4-1106-preview' | 'gpt-4' | 'gpt-4-0613' | 'gpt-3.5-turbo-0125' | 'gpt-3.5-turbo' | 'gpt-3.5-turbo-1106')", + "description": "OpenAI model to use.", "enum": [ "o1-preview", "o1-mini", @@ -83,65 +85,15 @@ "gpt-3.5-turbo-1106" ] }, - "void.openai.providerSettings": { - "type": "object", - "properties": { - "baseURL": { - "type": "string", - "description": "Use a different URL prefix for API calls, e.g. to use proxy servers." - }, - "headers": { - "type": "object", - "description": "Custom headers to include in the requests." - }, - "organization": { - "type": "string", - "description": "OpenAI Organization." - }, - "project": { - "type": "string", - "description": "OpenAI project." - }, - "compatibility": { - "type": "string", - "description": "OpenAI compatibility mode. Should be set to `strict` when using the OpenAI API, and `compatible` when using 3rd party providers. In `compatible` mode, newer information such as streamOptions are not being sent. Defaults to 'compatible'.", - "enum": [ - "strict", - "compatible" - ] - } - } - }, - "void.azure.apiKey": { + "void.ollama.endpoint": { "type": "string", - "description": "Azure API key." - }, - "void.azure.deploymentId": { - "type": "string", - "description": "Azure API deployment ID." - }, - "void.azure.resourceName": { - "type": "string", - "description": "Name of the Azure OpenAI resource. Either this or `baseURL` can be used. \nThe resource name is used in the assembled URL: `https://{resourceName}.openai.azure.com/openai/deployments/{modelId}{path}`" - }, - "void.azure.providerSettings": { - "type": "object", - "properties": { - "baseURL": { - "type": "string", - "default": "https://${resourceName}.openai.azure.com/openai/deployments", - "description": "Azure API base URL." - }, - "headers": { - "type": "object", - "description": "Custom headers to include in the requests." - } - } + "default": "http://127.0.0.1:11434", + "description": "The Ollama endpoint. Start Ollama by running `OLLAMA_ORIGINS=\"vscode-webview://*\" ollama serve`" }, "void.ollama.model": { "type": "string", - "description": "Ollama model. 'codegemma' | 'codegemma:2b' | 'codegemma:7b' | 'codellama' | 'codellama:7b' | 'codellama:13b' | 'codellama:34b' | 'codellama:70b' | 'codellama:code' | 'codellama:python' | 'command-r' | 'command-r:35b' | 'command-r-plus' | 'command-r-plus:104b' | 'deepseek-coder-v2' | 'deepseek-coder-v2:16b' | 'deepseek-coder-v2:236b' | 'falcon2' | 'falcon2:11b' | 'firefunction-v2' | 'firefunction-v2:70b' | 'gemma' | 'gemma:2b' | 'gemma:7b' | 'gemma2' | 'gemma2:2b' | 'gemma2:9b' | 'gemma2:27b' | 'llama2' | 'llama2:7b' | 'llama2:13b' | 'llama2:70b' | 'llama3' | 'llama3:8b' | 'llama3:70b' | 'llama3-chatqa' | 'llama3-chatqa:8b' | 'llama3-chatqa:70b' | 'llama3-gradient' | 'llama3-gradient:8b' | 'llama3-gradient:70b' | 'llama3.1' | 'llama3.1:8b' | 'llama3.1:70b' | 'llama3.1:405b' | 'llava' | 'llava:7b' | 'llava:13b' | 'llava:34b' | 'llava-llama3' | 'llava-llama3:8b' | 'llava-phi3' | 'llava-phi3:3.8b' | 'mistral' | 'mistral:7b' | 'mistral-large' | 'mistral-large:123b' | 'mistral-nemo' | 'mistral-nemo:12b' | 'mixtral' | 'mixtral:8x7b' | 'mixtral:8x22b' | 'moondream' | 'moondream:1.8b' | 'openhermes' | 'openhermes:v2.5' | 'phi3' | 'phi3:3.8b' | 'phi3:14b' | 'phi3.5' | 'phi3.5:3.8b' | 'qwen' | 'qwen:7b' | 'qwen:14b' | 'qwen:32b' | 'qwen:72b' | 'qwen:110b' | 'qwen2' | 'qwen2:0.5b' | 'qwen2:1.5b' | 'qwen2:7b' | 'qwen2:72b' | 'smollm' | 'smollm:135m' | 'smollm:360m' | 'smollm:1.7b'", "default": "llama3.1", + "description": "Ollama model to use.", "enum": [ "codegemma", "codegemma:2b", @@ -231,62 +183,73 @@ "smollm:1.7b" ] }, - "void.ollama.providerSettings": { + "void.openAICompatible.endpoint": { + "type": "string", + "default": "http://127.0.0.1:11434/v1", + "description": "The endpoint." + }, + "void.openAICompatible.model": { + "type": "string", + "default": "gpt-4o", + "description": "The name of the model to use." + }, + "void.openAICompatible.apiKey": { + "type": "string", + "default": "", + "description": "Your API key." + }, + "void.greptile.apiKey": { + "type": "string", + "default": "", + "description": "Greptile API key." + }, + "void.greptile.githubPAT": { + "type": "string", + "default": "", + "description": "Github PAT given to Greptile to access your repository." + }, + "void.greptile.remote": { + "type": "string", + "description": "remote provider", + "enum": [ + "github", + "gitlab" + ] + }, + "void.greptile.repository": { + "type": "string", + "description": "Repository identifier in \"owner/repository\" format." + }, + "void.greptile.branch": { + "type": "string", + "default": "main", + "description": "Name of the git branch." + }, + "void.azure.apiKey": { + "type": "string", + "description": "Azure API key." + }, + "void.azure.deploymentId": { + "type": "string", + "description": "Azure API deployment ID." + }, + "void.azure.resourceName": { + "type": "string", + "description": "Name of the Azure OpenAI resource. Either this or `baseURL` can be used. \nThe resource name is used in the assembled URL: `https://{resourceName}.openai.azure.com/openai/deployments/{modelId}{path}`" + }, + "void.azure.providerSettings": { "type": "object", "properties": { "baseURL": { "type": "string", - "default": "http://127.0.0.1:11434", - "description": "Ollama base URL. Local API server can be started with `OLLAMA_ORIGINS=* ollama serve`" + "default": "https://${resourceName}.openai.azure.com/openai/deployments", + "description": "Azure API base URL." }, "headers": { "type": "object", "description": "Custom headers to include in the requests." } } - }, - "void.greptile.apiKey": { - "type": "string", - "description": "Greptile API key." - }, - "void.greptile.providerSettings": { - "type": "object", - "properties": { - "headers": { - "type": "object", - "description": "Custom headers to include in the requests.", - "properties": { - "X-Github-Token": { - "type": "string", - "description": "GitHub Token." - } - } - }, - "repoinfo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "remote": { - "type": "string", - "description": "remote provider", - "enum": [ - "github", - "gitlab" - ] - }, - "repository": { - "type": "string", - "description": "repository identifier in \"owner/repository\" format." - }, - "branch": { - "type": "string", - "description": "git branch." - } - } - } - } - } } } }, @@ -306,13 +269,28 @@ { "command": "void.discardDiff", "title": "Discard Diff" + }, + { + "command": "void.startNewThread", + "title": "Start a new chat", + "icon": "$(add)" + }, + { + "command": "void.toggleThreadSelector", + "title": "View past chats", + "icon": "$(history)" + }, + { + "command": "void.openSettings", + "title": "Void settings", + "icon": "$(settings-gear)" } ], "viewsContainers": { "activitybar": [ { "id": "voidViewContainer", - "title": "My Extension", + "title": "Chat", "icon": "$(hubot)" } ] @@ -337,39 +315,54 @@ "key": "ctrl+k", "mac": "cmd+k" } - ] + ], + "menus": { + "view/title": [ + { + "command": "void.startNewThread", + "when": "view == 'void.viewnumberone'", + "group": "navigation" + }, + { + "command": "void.toggleThreadSelector", + "when": "view == 'void.viewnumberone'", + "group": "navigation" + }, + { + "command": "void.openSettings", + "when": "view == 'void.viewnumberone'", + "group": "navigation" + } + ] + } }, "scripts": { "vscode:prepublish": "npm run compile", - "compile": "tsc -p ./", "watch": "tsc -watch -p ./", "build": "rimraf dist && node build-tsx.js && node build-css.js", - "pretest": "npm run compile && npm run lint", - "lint": "eslint src --ext ts", + "pretest": "tsc -p ./ && eslint src --ext ts", "test": "vscode-test" }, "devDependencies": { "@eslint/js": "^9.9.1", "@types/diff": "^5.2.2", "@types/jest": "^29.5.12", - "@types/mocha": "^10.0.7", + "@types/mocha": "^10.0.8", "@types/node": "^22.5.1", "@types/react": "^18.3.4", "@types/react-dom": "^18.3.0", - "@types/vscode": "1.92.0", + "@types/vscode": "1.89.0", "@typescript-eslint/eslint-plugin": "^8.3.0", "@typescript-eslint/parser": "^8.3.0", - "@vscode/test-cli": "0.0.10", + "@vscode/test-cli": "^0.0.10", "@vscode/test-electron": "2.4.1", "autoprefixer": "^10.4.20", - "diff": "^6.0.0-beta", "esbuild": "^0.23.1", "eslint": "^8.57.0", "eslint-plugin-react": "^7.35.1", "eslint-plugin-react-hooks": "^4.6.2", "globals": "^15.9.0", "marked": "^14.1.0", - "ollama": "^0.5.8", "postcss": "^8.4.41", "react": "^18.3.1", "react-dom": "^18.3.1", @@ -384,8 +377,8 @@ "@ai-sdk/azure": "^0.0.39", "@ai-sdk/openai": "^0.0.60", "@anthropic-ai/sdk": "^0.27.1", - "ai": "^3.3.43", - "ollama-ai-provider": "^0.15.0", - "openai": "^4.57.0" + "ollama": "^0.5.9", + "openai": "^4.57.0", + "diff": "^7.0.0" } -} \ No newline at end of file +} diff --git a/extensions/void/src/SidebarWebviewProvider.ts b/extensions/void/src/SidebarWebviewProvider.ts index 13a28b9a..fe01c800 100644 --- a/extensions/void/src/SidebarWebviewProvider.ts +++ b/extensions/void/src/SidebarWebviewProvider.ts @@ -55,20 +55,7 @@ export class SidebarWebviewProvider implements vscode.WebviewViewProvider { const nonce = getNonce(); // only scripts with the nonce are allowed to run, this is a recommended security measure - const ollamaBaseURL = new URL('/', vscode.workspace.getConfiguration('void').get('ollama.providerSettings.baseURL') || 'http://127.0.0.1:11434').toString() - const azureResourceName = vscode.workspace.getConfiguration('void').get('azure.resourceName') ?? '' - const azureBaseURL = new URL('/', vscode.workspace.getConfiguration('void').get('azure.providerSettings.baseURL') || `https://${azureResourceName}.openai.azure.com/openai/deployments`).toString() - const openaiBaseURL = new URL('/', vscode.workspace.getConfiguration('void').get('openai.providerSettings.baseURL') || 'https://api.openai.com').toString() - const greptileBaseURL = new URL('/', vscode.workspace.getConfiguration('void').get('greptile.providerSettings.baseURL') || 'https://api.greptile.com').toString() - const anthropicBaseURL = new URL('/', vscode.workspace.getConfiguration('void').get('anthropic.providerSettings.baseURL') || 'https://api.anthropic.com').toString() - const allowed_urls = [ - ollamaBaseURL, - azureBaseURL, - openaiBaseURL, - greptileBaseURL, - anthropicBaseURL - ] - + const allowed_urls = ['https://api.anthropic.com', 'https://api.openai.com', 'https://api.greptile.com'] webview.html = ` diff --git a/extensions/void/src/common/getRules.ts b/extensions/void/src/common/getRules.ts deleted file mode 100644 index 0a7ef6c4..00000000 --- a/extensions/void/src/common/getRules.ts +++ /dev/null @@ -1,12 +0,0 @@ -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; - } -} diff --git a/extensions/void/src/extension.ts b/extensions/void/src/extension.ts index fa2805e8..4cd8ac26 100644 --- a/extensions/void/src/extension.ts +++ b/extensions/void/src/extension.ts @@ -1,7 +1,8 @@ import * as vscode from 'vscode'; import { WebviewMessage } from './shared_types'; +import { CtrlKCodeLensProvider } from './CtrlKCodeLensProvider'; import { getDiffedLines } from './getDiffedLines'; -import { ApprovalCodeLensProvider } from './ApprovalCodeLensProvider'; +import { ApprovalCodeLensProvider, SuggestedEdit } from './ApprovalCodeLensProvider'; import { SidebarWebviewProvider } from './SidebarWebviewProvider'; import { ApiConfig } from './common/sendLLMMessage'; @@ -12,43 +13,22 @@ const readFileContentOfUri = async (uri: vscode.Uri) => { const getApiConfig = () => { const apiConfig: ApiConfig = { - provider: vscode.workspace.getConfiguration('void').get('provider') ?? 'anthropic', - anthropic: { - model: vscode.workspace.getConfiguration('void').get('anthropic.model') ?? 'claude-3-5-sonnet-20240620', - apiKey: vscode.workspace.getConfiguration('void').get('anthropic.apiKey') ?? '', - providerSettings: { - ...vscode.workspace.getConfiguration('void').get('anthropic.providerSettings') ?? {}, - }, - }, - openai: { - model: vscode.workspace.getConfiguration('void').get('openai.model') ?? 'gpt-4o', - apiKey: vscode.workspace.getConfiguration('void').get('openai.apiKey') ?? '', - providerSettings: { - ...vscode.workspace.getConfiguration('void').get('openai.providerSettings') ?? {}, - }, - }, - azure: { - deploymentId: vscode.workspace.getConfiguration('void').get('azure.deploymentId') ?? '', - resourceName: vscode.workspace.getConfiguration('void').get('azure.resourceName') ?? '', - apiKey: vscode.workspace.getConfiguration('void').get('azure.apiKey') ?? '', - providerSettings: { - ...vscode.workspace.getConfiguration('void').get('azure.providerSettings') ?? {}, - }, - }, - ollama: { - model: vscode.workspace.getConfiguration('void').get('ollama.model') ?? 'llama3.1', - providerSettings: { - ...vscode.workspace.getConfiguration('void').get('ollama.providerSettings') ?? {}, - }, - }, + anthropic: { apikey: vscode.workspace.getConfiguration('void').get('anthropicApiKey') ?? '' }, + openai: { apikey: vscode.workspace.getConfiguration('void').get('openAIApiKey') ?? '' }, greptile: { - apiKey: vscode.workspace.getConfiguration('void').get('greptile.apiKey') ?? '', - providerSettings: { - ...vscode.workspace.getConfiguration('void').get('greptile.providerSettings') ?? {}, + apikey: vscode.workspace.getConfiguration('void').get('greptileApiKey') ?? '', + githubPAT: vscode.workspace.getConfiguration('void').get('githubPAT') ?? '', + repoinfo: { + remote: 'github', + repository: 'TODO', + branch: 'main' } }, + ollama: { + // apikey: vscode.workspace.getConfiguration('void').get('ollamaSettings') ?? '', + }, + whichApi: vscode.workspace.getConfiguration('void').get('whichApi') ?? '' } - return apiConfig } @@ -115,22 +95,7 @@ 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 === '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') { + if (m.type === 'requestFiles') { // get contents of all file paths const files = await Promise.all( diff --git a/extensions/void/src/shared_types.ts b/extensions/void/src/shared_types.ts index d443bbe6..4d7c0dc9 100644 --- a/extensions/void/src/shared_types.ts +++ b/extensions/void/src/shared_types.ts @@ -27,9 +27,6 @@ type WebviewMessage = ( // editor -> sidebar | { type: 'apiConfig', apiConfig: ApiConfig } - // sidebar -> editor - | { type: 'getRules', rules: string | null } - ) type Command = WebviewMessage['type'] diff --git a/extensions/void/src/sidebar/getVscodeApi.ts b/extensions/void/src/sidebar/getVscodeApi.ts index caf22e6e..890b31f2 100644 --- a/extensions/void/src/sidebar/getVscodeApi.ts +++ b/extensions/void/src/sidebar/getVscodeApi.ts @@ -9,8 +9,7 @@ const awaiting: { [c in Command]: ((res: any) => void)[] } = { "requestFiles": [], "files": [], "apiConfig": [], - "getApiConfig": [], - "getRules": [] + "getApiConfig": [] } // use this function to await responses