mirror of
https://github.com/hanzoai/code.git
synced 2026-09-30 20:53:35 +00:00
allowed urls updating when configuration changes
This commit is contained in:
@@ -18,6 +18,8 @@ export class SidebarWebviewProvider implements vscode.WebviewViewProvider {
|
||||
|
||||
private readonly _extensionUri: vscode.Uri
|
||||
private _res: (c: vscode.Webview) => void // used to resolve the webview
|
||||
private allowed_urls: string[] = ['https://api.anthropic.com', 'https://api.openai.com', 'https://api.greptile.com', 'http://localhost:11434'];
|
||||
private _webviewView?: vscode.WebviewView;
|
||||
|
||||
constructor(context: vscode.ExtensionContext) {
|
||||
// const extensionPath = context.extensionPath // the directory where the extension is installed, might be useful later, not sure for what though... was included in webviewProvider code
|
||||
@@ -27,6 +29,45 @@ export class SidebarWebviewProvider implements vscode.WebviewViewProvider {
|
||||
this.webview = new Promise((res, rej) => { temp_res = res })
|
||||
if (!temp_res) throw new Error("sidebar provider: resolver was undefined")
|
||||
this._res = temp_res
|
||||
|
||||
vscode.workspace.onDidChangeConfiguration(event => {
|
||||
if (event.affectsConfiguration('void.ollamaSettings.endpoint')) {
|
||||
this.updateAllowedUrls();
|
||||
// Regenerate the webview's HTML content
|
||||
if (this._webviewView) {
|
||||
this._webviewView.webview.html = this.getWebviewContent(this._webviewView.webview);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private getWebviewContent(webview: vscode.Webview): string {
|
||||
const scriptUri = webview.asWebviewUri(vscode.Uri.joinPath(this._extensionUri, 'dist/sidebar/index.js'));
|
||||
const stylesUri = webview.asWebviewUri(vscode.Uri.joinPath(this._extensionUri, 'dist/sidebar/styles.css'));
|
||||
const rootUri = webview.asWebviewUri(vscode.Uri.joinPath(this._extensionUri));
|
||||
const nonce = getNonce();
|
||||
|
||||
const allowed_urls = this.allowed_urls;
|
||||
return `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Custom View</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; connect-src ${allowed_urls.join(' ')}; img-src vscode-resource: https:; script-src 'nonce-${nonce}'; style-src vscode-resource: 'unsafe-inline' http: https: data:;">
|
||||
<base href="${rootUri}/">
|
||||
<link href="${stylesUri}" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script nonce="${nonce}" src="${scriptUri}"></script>
|
||||
</body>
|
||||
</html>`;
|
||||
}
|
||||
|
||||
private updateAllowedUrls() {
|
||||
const ollamaEndpoint: string = vscode.workspace.getConfiguration('void').get('ollamaSettings.endpoint') || 'http://localhost:11434';
|
||||
this.allowed_urls = ['https://api.anthropic.com', 'https://api.openai.com', 'https://api.greptile.com', ollamaEndpoint];
|
||||
}
|
||||
|
||||
// called internally by vscode
|
||||
@@ -35,6 +76,7 @@ export class SidebarWebviewProvider implements vscode.WebviewViewProvider {
|
||||
context: vscode.WebviewViewResolveContext,
|
||||
token: vscode.CancellationToken,
|
||||
) {
|
||||
this._webviewView = webviewView;
|
||||
|
||||
const webview = webviewView.webview
|
||||
|
||||
@@ -54,25 +96,10 @@ export class SidebarWebviewProvider implements vscode.WebviewViewProvider {
|
||||
|
||||
const nonce = getNonce(); // only scripts with the nonce are allowed to run, this is a recommended security measure
|
||||
|
||||
// Allow Ollama endpoint
|
||||
const ollamaEndpoint = vscode.workspace.getConfiguration('void').get('ollamaSettings.endpoint') || 'http://localhost:11434'
|
||||
const allowed_urls = ['https://api.anthropic.com', 'https://api.openai.com', 'https://api.greptile.com', ollamaEndpoint ]
|
||||
webview.html = `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Custom View</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; connect-src ${allowed_urls.join(' ')}; img-src vscode-resource: https:; script-src 'nonce-${nonce}';style-src vscode-resource: 'unsafe-inline' http: https: data:;">
|
||||
<base href="${rootUri}/">
|
||||
<link href="${stylesUri}" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script nonce="${nonce}" src="${scriptUri}"></script>
|
||||
</body>
|
||||
</html>`;
|
||||
|
||||
// Regenerate the Sidebar html whenever the allowed_urls changes
|
||||
this.updateAllowedUrls();
|
||||
const allowed_urls = this.allowed_urls;
|
||||
webview.html = this.getWebviewContent(webview);
|
||||
|
||||
this._res(webview);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import Anthropic from '@anthropic-ai/sdk';
|
||||
import OpenAI from 'openai';
|
||||
import { Ollama } from 'ollama/browser'
|
||||
import { getVSCodeAPI } from '../sidebar/getVscodeApi';
|
||||
|
||||
|
||||
export type ApiConfig = {
|
||||
anthropic: {
|
||||
@@ -220,9 +222,21 @@ const sendGreptileMsg: SendLLMMessageFnTypeInternal = ({ messages, onText, onFin
|
||||
export const sendLLMMessage: SendLLMMessageFnTypeExternal = ({ messages, onText, onFinalMessage, apiConfig }) => {
|
||||
if (!apiConfig) return { abort: () => { } }
|
||||
|
||||
const whichApi = apiConfig.whichApi;
|
||||
if (
|
||||
apiConfig.anthropic.apikey === "" &&
|
||||
apiConfig.greptile.apikey === "" &&
|
||||
apiConfig.openai.apikey === "" &&
|
||||
apiConfig.ollama.endpoint === "" &&
|
||||
apiConfig.ollama.model === ""
|
||||
) {
|
||||
getVSCodeAPI().postMessage({ type: 'displayError', message: 'Required API keys are not set.' })
|
||||
onFinalMessage("Required API keys are not set.");
|
||||
return { abort: () => { }}
|
||||
}
|
||||
|
||||
switch (whichApi) {
|
||||
|
||||
|
||||
switch (apiConfig.whichApi) {
|
||||
case 'anthropic':
|
||||
return sendClaudeMsg({ messages, onText, onFinalMessage, apiConfig });
|
||||
case 'openai':
|
||||
@@ -232,8 +246,9 @@ export const sendLLMMessage: SendLLMMessageFnTypeExternal = ({ messages, onText,
|
||||
case 'ollama':
|
||||
return sendOllamaMsg({ messages, onText, onFinalMessage, apiConfig });
|
||||
default:
|
||||
console.error(`Error: whichApi was ${whichApi}, which is not recognized!`);
|
||||
return sendClaudeMsg({ messages, onText, onFinalMessage, apiConfig }); // TODO
|
||||
console.error(`Error: whichApi was ${apiConfig.whichApi}, which is not recognized!`);
|
||||
return { abort: () => { } }
|
||||
//return sendClaudeMsg({ messages, onText, onFinalMessage, apiConfig }); // TODO
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ const getApiConfig = () => {
|
||||
return apiConfig
|
||||
}
|
||||
|
||||
|
||||
export function activate(context: vscode.ExtensionContext) {
|
||||
|
||||
// 1. Mount the chat sidebar
|
||||
@@ -116,14 +117,16 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
const oldContents = await readFileContentOfUri(editor.document.uri)
|
||||
const suggestedEdits = getDiffedLines(oldContents, m.code)
|
||||
await approvalCodeLensProvider.addNewApprovals(editor, suggestedEdits)
|
||||
}
|
||||
else if (m.type === 'getApiConfig') {
|
||||
} else if (m.type === 'getApiConfig') {
|
||||
|
||||
const apiConfig = getApiConfig()
|
||||
console.log('Api config:', apiConfig)
|
||||
|
||||
webview.postMessage({ type: 'apiConfig', apiConfig } satisfies WebviewMessage)
|
||||
|
||||
} else if (m.type === 'displayError') {
|
||||
|
||||
vscode.window.showWarningMessage(m.message, { modal: true });
|
||||
}
|
||||
else {
|
||||
|
||||
|
||||
@@ -27,6 +27,9 @@ type WebviewMessage = (
|
||||
// editor -> sidebar
|
||||
| { type: 'apiConfig', apiConfig: ApiConfig }
|
||||
|
||||
// Display native vscode error
|
||||
| { type: 'displayError', message: string } //
|
||||
|
||||
)
|
||||
|
||||
type Command = WebviewMessage['type']
|
||||
|
||||
@@ -166,6 +166,7 @@ const Sidebar = () => {
|
||||
// if user pressed ctrl+l, add their selection to the sidebar
|
||||
if (m.type === 'ctrl+l') {
|
||||
|
||||
|
||||
setSelection(m.selection)
|
||||
|
||||
const filepath = m.selection.filePath
|
||||
@@ -223,10 +224,12 @@ const Sidebar = () => {
|
||||
},
|
||||
apiConfig: apiConfig
|
||||
})
|
||||
abortFnRef.current = abort
|
||||
|
||||
|
||||
abortFnRef.current = abort
|
||||
}
|
||||
|
||||
|
||||
const onStop = useCallback(() => {
|
||||
// abort claude
|
||||
abortFnRef.current?.()
|
||||
@@ -266,7 +269,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": [],
|
||||
"displayError": []
|
||||
}
|
||||
|
||||
// use this function to await responses
|
||||
|
||||
Reference in New Issue
Block a user