From 6d609d2fd7cf017ef573a8fce924d0a973407ea0 Mon Sep 17 00:00:00 2001 From: rj Date: Wed, 16 Oct 2024 19:48:37 +0100 Subject: [PATCH] development > main (#349) * updates and other things * 3.17.28 --- package-lock.json | 4 +- package.json | 72 ++++++-------- src/common/constants.ts | 1 + src/extension/providers/base.ts | 10 ++ src/index.ts | 7 -- src/webview/hooks.ts | 120 +++++++++++++----------- src/webview/icons.tsx | 43 --------- src/webview/settings.tsx | 17 +++- src/webview/styles/providers.module.css | 6 +- 9 files changed, 125 insertions(+), 155 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4d1de1a5..03fb1102 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "twinny", - "version": "3.17.27", + "version": "3.17.28", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "twinny", - "version": "3.17.27", + "version": "3.17.28", "cpu": [ "x64", "arm64" diff --git a/package.json b/package.json index 51f23dc3..56f489d1 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "twinny", "displayName": "twinny - AI Code Completion and Chat", "description": "Locally hosted AI code completion plugin for vscode", - "version": "3.17.27", + "version": "3.17.28", "icon": "assets/icon.png", "keywords": [ "code-inference", @@ -107,30 +107,25 @@ "group": "navigation@4", "when": "view == twinny.sidebar" }, - { - "command": "twinny.templates", - "when": "view == twinny.sidebar", - "group": "navigation@5" - }, { "command": "twinny.conversationHistory", "when": "view == twinny.sidebar", - "group": "navigation@6" + "group": "navigation@5" }, { "command": "twinny.openPanelChat", "when": "view == twinny.sidebar", - "group": "navigation@7" + "group": "navigation@6" }, { "command": "twinny.newConversation", "when": "view == twinny.sidebar", - "group": "navigation@8" + "group": "navigation@7" }, { "command": "twinny.settings", "when": "view == twinny.sidebar", - "group": "navigation@9" + "group": "navigation@8" } ] }, @@ -278,7 +273,7 @@ "order": 0, "type": "boolean", "default": true, - "description": "Activates or deactivates the Twinny extension." + "markdownDescription": "Toggles the Twinny extension on or off. When `true`, Twinny is active and ready to provide completions." }, "twinny.enabledLanguages": { "order": 1, @@ -289,40 +284,40 @@ "default": { "*": true }, - "markdownDescription": "Languages to enable completions with Twinny for. `*` is used as the default." + "markdownDescription": "Specifies which languages to enable completions with Twinny for. Use `*` as the default for all languages. Example:\n```json\n{\n \"*\": true,\n \"python\": true,\n \"javascript\": false\n}\n```" }, "twinny.autoSuggestEnabled": { "order": 2, "type": "boolean", "default": true, - "description": "Enable automatic completion suggestions, manual trigger (default shortcut Alt+\\)." + "markdownDescription": "When `true`, Twinny will automatically suggest completions. You can still manually trigger completions using the default shortcut (`Alt+\\`)." }, "twinny.contextLength": { "order": 3, "type": "number", "default": 100, - "description": "Defines the number of lines before and after the current line to include in FIM prompts.", + "markdownDescription": "Specifies how many lines of context (before and after the current line) to include in Fill-in-Middle (FIM) prompts. A higher number provides more context but may slow down completions.", "required": true }, "twinny.debounceWait": { "order": 4, "type": "number", "default": 300, - "description": "Delay in milliseconds before triggering the next completion.", + "markdownDescription": "Sets the delay (in milliseconds) before triggering the next completion. This helps reduce API calls and improve performance.", "required": true }, "twinny.temperature": { "order": 5, "type": "number", "default": 0.2, - "description": "Sets the model's creativity level (temperature) for generating completions.", + "markdownDescription": "Controls the randomness of the model's output. Lower values (e.g., 0.2) produce more focused and deterministic outputs, while higher values (e.g., 0.8) lead to more diverse and creative completions.", "required": true }, "twinny.multilineCompletionsEnabled": { "order": 6, "type": "boolean", "default": true, - "description": "Experimental feature: enables the generation of multi-line completions." + "markdownDescription": "When `true`, Twinny will attempt to generate multi-line completions. This is an experimental feature and may not work perfectly in all scenarios." }, "twinny.maxLines": { "dependencies": { @@ -331,90 +326,83 @@ "order": 7, "type": "number", "default": 30, - "description": "Maximum number of lines to use for multi line completions. Applicable only when multilineCompletionsEnabled is enabled." + "markdownDescription": "Sets the maximum number of lines for multi-line completions. Only applies when `twinny.multilineCompletionsEnabled` is `true`." }, "twinny.fileContextEnabled": { "order": 9, "type": "boolean", "default": false, - "description": "Enables scanning of neighbouring documents to enhance completion prompts. (Experimental)" + "markdownDescription": "When `true`, Twinny will scan neighboring documents to provide more context for completions. This is an experimental feature and may impact performance." }, "twinny.completionCacheEnabled": { "order": 10, "type": "boolean", "default": false, - "description": "Caches FIM completions for identical prompts to enhance performance." + "markdownDescription": "Enables caching of Fill-in-Middle (FIM) completions for identical prompts. This can significantly improve performance but may use more memory." }, "twinny.numPredictChat": { "order": 11, "type": "number", "default": 512, - "description": "Maximum token limit for chat completions.", + "markdownDescription": "Sets the maximum number of tokens to generate for chat completions. Higher values allow for longer completions but may increase response time.", "required": true }, "twinny.numPredictFim": { "order": 12, "type": "number", "default": 512, - "description": "Maximum token limit for FIM completions. Set to -1 for no limit. Twinny should stop at logical line breaks.", + "markdownDescription": "Defines the maximum number of tokens for Fill-in-Middle (FIM) completions. Use `-1` for no limit. Twinny will attempt to stop at logical line breaks regardless of this setting.", "required": true }, "twinny.enableSubsequentCompletions": { "order": 13, "type": "boolean", "default": true, - "description": "Enable this setting to allow twinny to keep making subsequent completion requests to the API after the last completion request was accepted." + "markdownDescription": "When `true`, Twinny will continue to make completion requests to the API after the previous completion was accepted. This can provide a more fluid completion experience." }, "twinny.ollamaHostname": { "order": 14, "type": "string", "default": "0.0.0.0", - "description": "Hostname for Ollama API.", + "markdownDescription": "Specifies the hostname for the Ollama API. Use `0.0.0.0` for localhost or provide a specific IP address or domain name.", "required": true }, "twinny.ollamaApiPort": { "order": 15, "type": "number", "default": 11434, - "description": "The API port usually `11434`", - "required": false - }, - "twinny.embeddingModel": { - "order": 16, - "type": "string", - "default": "nomic-embed-text", - "description": "The embedding model to use (Ollama only)", + "markdownDescription": "Sets the port number for the Ollama API. The default is `11434`, but you can change it if your Ollama instance uses a different port.", "required": false }, "twinny.keepAlive": { - "order": 17, + "order": 16, "type": "string", "default": "5m", - "description": "Keep models in memory by making requests with keep_alive=-1. Applicable only for Ollama API." + "markdownDescription": "Sets the duration to keep models in memory for Ollama API. Use formats like `5m` for 5 minutes or `1h` for 1 hour. Set to `-1` to keep models in memory indefinitely." }, "twinny.ollamaUseTls": { - "order": 18, + "order": 17, "type": "boolean", "default": false, - "description": "Enables TLS encryption Ollama API connections." + "markdownDescription": "When `true`, Twinny will use TLS encryption for connections to the Ollama API. Ensure your Ollama instance is configured for TLS before enabling this option." }, "twinny.enableLogging": { - "order": 19, + "order": 18, "type": "boolean", "default": true, - "description": "Enable twinny debug mode" + "markdownDescription": "Activates debug logging for Twinny. When `true`, Twinny will output detailed logs, which can be helpful for troubleshooting." }, "twinny.symmetryServerKey": { - "order": 20, + "order": 19, "type": "string", - "description": "The symmetry master server key.", + "markdownDescription": "Sets the symmetry master server key. Default value is provided for twinny's Symmetry server.", "default": "4b4a9cc325d134dee6679e9407420023531fd7e96c563f6c5d00fd5549b77435" }, "twinny.githubToken": { - "order": 28, + "order": 20, "type": "string", "default": "", - "description": "Your GitHub token. Used for fetching GitHub data." + "markdownDescription": "Your personal GitHub access token. This is used for fetching data from GitHub repositories. Keep this token secure and do not share it." } } } diff --git a/src/common/constants.ts b/src/common/constants.ts index 6e763458..b594cca4 100644 --- a/src/common/constants.ts +++ b/src/common/constants.ts @@ -76,6 +76,7 @@ export const EVENT_NAME = { twinnySetSessionContext: "twinny-set-session-context", twinnySetTab: "twinny-set-tab", twinnySetWorkspaceContext: "twinny-set-workspace-context", + twinnyEditDefaultTemplates: "twinny-edit-default-templates", twinnyStartSymmetryProvider: "twinny-start-symmetry-provider", twinnyStopGeneration: "twinny-stop-generation", twinnyStopSymmetryProvider: "twinny-stop-symmetry-provider", diff --git a/src/extension/providers/base.ts b/src/extension/providers/base.ts index c34582eb..6f2ec12e 100644 --- a/src/extension/providers/base.ts +++ b/src/extension/providers/base.ts @@ -143,6 +143,7 @@ export class BaseProvider { [EVENT_NAME.twinnyTextSelection]: this.getSelectedText, [EVENT_NAME.twinnyFileListRequest]: this.fileListRequest, [EVENT_NAME.twinnyNewConversation]: this.twinnyNewConversation, + [EVENT_NAME.twinnyEditDefaultTemplates]: this.editDefaultTemplates, [TWINNY_COMMAND_NAME.settings]: this.openSettings } this.webView?.onDidReceiveMessage((message: ClientMessage) => { @@ -168,6 +169,15 @@ export class BaseProvider { ) } + public editDefaultTemplates = async () => { + if (!this._templateDir) return + await vscode.commands.executeCommand( + "vscode.openFolder", + vscode.Uri.file(this._templateDir), + true + ) + } + public destroyStream = () => { this._chatService?.destroyStream() this.webView?.postMessage({ diff --git a/src/index.ts b/src/index.ts index 38a41923..30fe6e5d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -129,13 +129,6 @@ export async function activate(context: ExtensionContext) { completionProvider.onError() sidebarProvider.destroyStream() }), - commands.registerCommand(TWINNY_COMMAND_NAME.templates, async () => { - await vscode.commands.executeCommand( - "vscode.openFolder", - vscode.Uri.file(templateDir), - true - ) - }), commands.registerCommand(TWINNY_COMMAND_NAME.manageProviders, async () => { commands.executeCommand( "setContext", diff --git a/src/webview/hooks.ts b/src/webview/hooks.ts index 5abfdbe6..43de8cfe 100644 --- a/src/webview/hooks.ts +++ b/src/webview/hooks.ts @@ -5,7 +5,7 @@ import { useEffect, useMemo, useRef, - useState, + useState } from "react" import { MentionNodeAttrs } from "@tiptap/extension-mention" import { ReactRenderer } from "@tiptap/react" @@ -19,7 +19,7 @@ import { GITHUB_EVENT_NAME, GLOBAL_STORAGE_KEY, PROVIDER_EVENT_NAME, - WORKSPACE_STORAGE_KEY, + WORKSPACE_STORAGE_KEY } from "../common/constants" import { ApiModel, @@ -31,7 +31,7 @@ import { ServerMessage, SymmetryConnection, SymmetryModelProvider, - ThemeType, + ThemeType } from "../common/types" import { TwinnyProvider } from "../extension/provider-manager" @@ -53,7 +53,7 @@ export const useSelection = (onSelect?: () => void) => { useEffect(() => { window.addEventListener("message", handler) global.vscode.postMessage({ - type: EVENT_NAME.twinnyTextSelection, + type: EVENT_NAME.twinnyTextSelection }) return () => window.removeEventListener("message", handler) }, []) @@ -76,7 +76,7 @@ export const useGlobalContext = (key: string) => { global.vscode.postMessage({ type: EVENT_NAME.twinnySetGlobalContext, key, - data: value, + data: value }) } @@ -85,7 +85,7 @@ export const useGlobalContext = (key: string) => { global.vscode.postMessage({ type: EVENT_NAME.twinnyGlobalContext, - key, + key }) return () => window.removeEventListener("message", handler) @@ -108,7 +108,7 @@ export const useSessionContext = (key: string) => { window.addEventListener("message", handler) global.vscode.postMessage({ type: EVENT_NAME.twinnySessionContext, - key, + key }) return () => window.removeEventListener("message", handler) }, []) @@ -130,7 +130,7 @@ export const useWorkSpaceContext = (key: string) => { window.addEventListener("message", handler) global.vscode.postMessage({ type: EVENT_NAME.twinnyGetWorkspaceContext, - key, + key }) return () => window.removeEventListener("message", handler) @@ -150,7 +150,7 @@ export const useTheme = () => { } useEffect(() => { global.vscode.postMessage({ - type: EVENT_NAME.twinnySendTheme, + type: EVENT_NAME.twinnySendTheme }) window.addEventListener("message", handler) return () => window.removeEventListener("message", handler) @@ -169,7 +169,7 @@ export const useLoading = () => { } useEffect(() => { global.vscode.postMessage({ - type: EVENT_NAME.twinnySendLoader, + type: EVENT_NAME.twinnySendLoader }) window.addEventListener("message", handler) return () => window.removeEventListener("message", handler) @@ -188,7 +188,7 @@ export const useLanguage = (): LanguageType | undefined => { } useEffect(() => { global.vscode.postMessage({ - type: EVENT_NAME.twinnySendLanguage, + type: EVENT_NAME.twinnySendLanguage }) window.addEventListener("message", handler) return () => window.removeEventListener("message", handler) @@ -210,18 +210,24 @@ export const useTemplates = () => { global.vscode.postMessage({ type: EVENT_NAME.twinnySetWorkspaceContext, key: WORKSPACE_STORAGE_KEY.selectedTemplates, - data: templates, + data: templates } as ClientMessage) } + const editDefaultTemplates = () => { + global.vscode.postMessage({ + type: EVENT_NAME.twinnyEditDefaultTemplates + }) + } + useEffect(() => { global.vscode.postMessage({ - type: EVENT_NAME.twinnyListTemplates, + type: EVENT_NAME.twinnyListTemplates }) window.addEventListener("message", handler) return () => window.removeEventListener("message", handler) }, []) - return { templates, saveTemplates } + return { templates, saveTemplates, editDefaultTemplates } } export const useGithubPRs = () => { @@ -245,7 +251,7 @@ export const useGithubPRs = () => { setIsLoading(true) global.vscode.postMessage({ type: GITHUB_EVENT_NAME.getPullRequests, - data: { owner, repo }, + data: { owner, repo } }) } @@ -259,7 +265,7 @@ export const useGithubPRs = () => { global.vscode.postMessage({ type: GITHUB_EVENT_NAME.getPullRequestReview, - data: { owner, repo, number: selectedPR, title }, + data: { owner, repo, number: selectedPR, title } }) } @@ -267,7 +273,7 @@ export const useGithubPRs = () => { prs, isLoading, getPrs, - startReview, + startReview } } @@ -310,49 +316,49 @@ export const useProviders = () => { const saveProvider = (provider: TwinnyProvider) => { global.vscode.postMessage({ type: PROVIDER_EVENT_NAME.addProvider, - data: provider, + data: provider } as ClientMessage) } const copyProvider = (provider: TwinnyProvider) => { global.vscode.postMessage({ type: PROVIDER_EVENT_NAME.copyProvider, - data: provider, + data: provider } as ClientMessage) } const updateProvider = (provider: TwinnyProvider) => { global.vscode.postMessage({ type: PROVIDER_EVENT_NAME.updateProvider, - data: provider, + data: provider } as ClientMessage) } const removeProvider = (provider: TwinnyProvider) => { global.vscode.postMessage({ type: PROVIDER_EVENT_NAME.removeProvider, - data: provider, + data: provider } as ClientMessage) } const setActiveFimProvider = (provider: TwinnyProvider) => { global.vscode.postMessage({ type: PROVIDER_EVENT_NAME.setActiveFimProvider, - data: provider, + data: provider } as ClientMessage) } const setActiveEmbeddingsProvider = (provider: TwinnyProvider) => { global.vscode.postMessage({ type: PROVIDER_EVENT_NAME.setActiveEmbeddingsProvider, - data: provider, + data: provider } as ClientMessage) } const setActiveChatProvider = (provider: TwinnyProvider) => { global.vscode.postMessage({ type: PROVIDER_EVENT_NAME.setActiveChatProvider, - data: provider, + data: provider } as ClientMessage) } @@ -364,22 +370,22 @@ export const useProviders = () => { const resetProviders = () => { global.vscode.postMessage({ - type: PROVIDER_EVENT_NAME.resetProvidersToDefaults, + type: PROVIDER_EVENT_NAME.resetProvidersToDefaults } as ClientMessage) } useEffect(() => { global.vscode.postMessage({ - type: PROVIDER_EVENT_NAME.getAllProviders, + type: PROVIDER_EVENT_NAME.getAllProviders }) global.vscode.postMessage({ - type: PROVIDER_EVENT_NAME.getActiveChatProvider, + type: PROVIDER_EVENT_NAME.getActiveChatProvider }) global.vscode.postMessage({ - type: PROVIDER_EVENT_NAME.getActiveFimProvider, + type: PROVIDER_EVENT_NAME.getActiveFimProvider }) global.vscode.postMessage({ - type: PROVIDER_EVENT_NAME.getActiveEmbeddingsProvider, + type: PROVIDER_EVENT_NAME.getActiveEmbeddingsProvider }) window.addEventListener("message", handler) return () => window.removeEventListener("message", handler) @@ -398,7 +404,7 @@ export const useProviders = () => { setActiveChatProvider, setActiveEmbeddingsProvider, setActiveFimProvider, - updateProvider, + updateProvider } } @@ -420,7 +426,7 @@ export const useConfigurationSetting = (key: string) => { useEffect(() => { global.vscode.postMessage({ type: EVENT_NAME.twinnyGetConfigValue, - key, + key }) window.addEventListener("message", handler) return () => window.removeEventListener("message", handler) @@ -437,27 +443,27 @@ export const useConversationHistory = () => { const getConversations = () => { global.vscode.postMessage({ - type: CONVERSATION_EVENT_NAME.getConversations, + type: CONVERSATION_EVENT_NAME.getConversations } as ClientMessage) } const getActiveConversation = () => { global.vscode.postMessage({ - type: CONVERSATION_EVENT_NAME.getActiveConversation, + type: CONVERSATION_EVENT_NAME.getActiveConversation }) } const removeConversation = (conversation: Conversation) => { global.vscode.postMessage({ type: CONVERSATION_EVENT_NAME.removeConversation, - data: conversation, + data: conversation } as ClientMessage) } const setActiveConversation = (conversation: Conversation | undefined) => { global.vscode.postMessage({ type: CONVERSATION_EVENT_NAME.setActiveConversation, - data: conversation, + data: conversation } as ClientMessage) setConversation(conversation) } @@ -465,13 +471,13 @@ export const useConversationHistory = () => { const saveLastConversation = (conversation: Conversation | undefined) => { global.vscode.postMessage({ type: CONVERSATION_EVENT_NAME.saveConversation, - data: conversation, + data: conversation } as ClientMessage) } const clearAllConversations = () => { global.vscode.postMessage({ - type: CONVERSATION_EVENT_NAME.clearAllConversations, + type: CONVERSATION_EVENT_NAME.clearAllConversations } as ClientMessage) } @@ -502,7 +508,7 @@ export const useConversationHistory = () => { removeConversation, saveLastConversation, clearAllConversations, - setActiveConversation, + setActiveConversation } } @@ -518,7 +524,7 @@ export const useOllamaModels = () => { useEffect(() => { global.vscode.postMessage({ - type: EVENT_NAME.twinnyFetchOllamaModels, + type: EVENT_NAME.twinnyFetchOllamaModels }) window.addEventListener("message", handler) return () => window.removeEventListener("message", handler) @@ -555,7 +561,7 @@ export const useFilePaths = () => { useEffect(() => { global.vscode.postMessage({ - type: EVENT_NAME.twinnyFileListRequest, + type: EVENT_NAME.twinnyFileListRequest }) window.addEventListener("message", handler) @@ -563,7 +569,7 @@ export const useFilePaths = () => { }, []) return { - filePaths: filePaths.current || [], + filePaths: filePaths.current || [] } } @@ -577,11 +583,11 @@ export const useSuggestion = () => { const filePaths = getFilePaths() const fileItems: FileItem[] = filePaths.map((path) => ({ name: path.split("/").pop() || "", - path: path, + path: path })) const defaultItems: FileItem[] = [ { name: "workspace", path: "workspace" }, - { name: "problems", path: "problems" }, + { name: "problems", path: "problems" } ] return Promise.resolve( [...defaultItems, ...fileItems] @@ -605,7 +611,7 @@ export const useSuggestion = () => { onStart: (props: SuggestionProps) => { reactRenderer = new ReactRenderer(MentionList, { props, - editor: props.editor, + editor: props.editor }) const getReferenceClientRect = props.clientRect as () => DOMRect @@ -617,7 +623,7 @@ export const useSuggestion = () => { showOnCreate: true, interactive: true, trigger: "manual", - placement: "bottom-start", + placement: "bottom-start" }) }, @@ -626,7 +632,7 @@ export const useSuggestion = () => { if (popup) { popup[0].setProps({ - getReferenceClientRect: props.clientRect as () => DOMRect, + getReferenceClientRect: props.clientRect as () => DOMRect }) } }, @@ -647,21 +653,21 @@ export const useSuggestion = () => { popup[0].destroy() reactRenderer.destroy() } - }, + } } }, []) const suggestion = useMemo( () => ({ items, - render, + render }), [items, render] ) return { suggestion, - filePaths, + filePaths } } @@ -672,21 +678,21 @@ export const useSymmetryConnection = () => { useState(null) const { context: symmetryConnectionSession, - setContext: setSymmetryConnectionSession, + setContext: setSymmetryConnectionSession } = useSessionContext( EXTENSION_SESSION_NAME.twinnySymmetryConnection ) const { context: symmetryProviderStatus, - setContext: setSymmetryProviderStatus, + setContext: setSymmetryProviderStatus } = useSessionContext( EXTENSION_SESSION_NAME.twinnySymmetryConnectionProvider ) const { context: autoConnectProviderContext, - setContext: setAutoConnectProviderContext, + setContext: setAutoConnectProviderContext } = useGlobalContext(GLOBAL_STORAGE_KEY.autoConnectSymmetryProvider) const isProviderConnected = symmetryProviderStatus === "connected" @@ -695,26 +701,26 @@ export const useSymmetryConnection = () => { setConnecting(true) global.vscode.postMessage({ type: EVENT_NAME.twinnyConnectSymmetry, - data: selectedModel, + data: selectedModel } as ClientMessage) } const disconnectSymmetry = () => { setConnecting(true) global.vscode.postMessage({ - type: EVENT_NAME.twinnyDisconnectSymmetry, + type: EVENT_NAME.twinnyDisconnectSymmetry } as ClientMessage) } const connectAsProvider = () => { global.vscode.postMessage({ - type: EVENT_NAME.twinnyStartSymmetryProvider, + type: EVENT_NAME.twinnyStartSymmetryProvider } as ClientMessage) } const disconnectAsProvider = () => { global.vscode.postMessage({ - type: EVENT_NAME.twinnyStopSymmetryProvider, + type: EVENT_NAME.twinnyStopSymmetryProvider } as ClientMessage) } @@ -772,7 +778,7 @@ export const useSymmetryConnection = () => { isProviderConnected, setAutoConnectProviderContext, symmetryConnection: symmetryConnectionSession, - symmetryProviderStatus, + symmetryProviderStatus } } diff --git a/src/webview/icons.tsx b/src/webview/icons.tsx index ed107fa5..4500ab0d 100644 --- a/src/webview/icons.tsx +++ b/src/webview/icons.tsx @@ -53,46 +53,3 @@ export const DisabledAutoScrollIcon = () => ( /> ) - -export const RAGIcon = ({ enabled }: { enabled: boolean }) => ( - - - - - - -) - -export const EnabledRAGIcon = () => -export const DisabledRAGIcon = () => diff --git a/src/webview/settings.tsx b/src/webview/settings.tsx index 065de515..5f671448 100644 --- a/src/webview/settings.tsx +++ b/src/webview/settings.tsx @@ -2,7 +2,7 @@ import { VSCodeButton, VSCodeCheckbox } from "@vscode/webview-ui-toolkit/react" import { DEFAULT_ACTION_TEMPLATES, - WORKSPACE_STORAGE_KEY, + WORKSPACE_STORAGE_KEY } from "../common/constants" import { useTemplates, useWorkSpaceContext } from "./hooks" @@ -11,8 +11,11 @@ import { kebabToSentence } from "./utils" import styles from "./styles/index.module.css" export const Settings = () => { - const { templates, saveTemplates } = useTemplates() - const { context: selectedTemplatesContext, setContext: setSelectedTemplatesContext} = + const { templates, saveTemplates, editDefaultTemplates } = useTemplates() + const { + context: selectedTemplatesContext, + setContext: setSelectedTemplatesContext + } = useWorkSpaceContext(WORKSPACE_STORAGE_KEY.selectedTemplates) || [] const handleTemplateClick = ( @@ -50,9 +53,17 @@ export const Settings = () => { setSelectedTemplatesContext(DEFAULT_ACTION_TEMPLATES) } + const handleEditDefaultTemplates = () => { + editDefaultTemplates() + } return ( <> +

Edit default templates

+

Edit the default templates used in the twinny extension.

+ + Open template editor +

Template settings

Select the templates you want to use in the chat interface.

{templates && diff --git a/src/webview/styles/providers.module.css b/src/webview/styles/providers.module.css index f613a9c3..2325514e 100644 --- a/src/webview/styles/providers.module.css +++ b/src/webview/styles/providers.module.css @@ -19,10 +19,14 @@ .provider { padding: 5px; - border-radius: 5px; background: var(--vscode-inputOption-hoverBackground); border: 1px solid var(--vscode-editorWidget-border); margin: 5px 0; + border-radius: 2px; +} + +.provider vscode-text-field { + width: unset; } .providerHeader {