├── .eslintrc.json
├── .gitignore
├── .vscode
├── extensions.json
├── launch.json
├── settings.json
└── tasks.json
├── .vscodeignore
├── .yarnrc
├── CHANGELOG.md
├── README.md
├── examples
├── create.png
├── explain.png
├── main.png
└── refactor.png
├── media
├── main.js
└── scripts
│ ├── microlight.min.js
│ ├── showdown.min.js
│ └── tailwind.min.js
├── package-lock.json
├── package.json
├── resources
├── buy-default-yellow-small.png
├── extensionIcon.png
└── icon.png
├── src
└── extension.ts
├── tsconfig.json
├── vsc-extension-quickstart.md
├── webpack.config.js
└── yarn.lock
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "parser": "@typescript-eslint/parser",
4 | "parserOptions": {
5 | "ecmaVersion": 6,
6 | "sourceType": "module"
7 | },
8 | "plugins": [
9 | "@typescript-eslint"
10 | ],
11 | "rules": {
12 | "@typescript-eslint/naming-convention": "warn",
13 | "@typescript-eslint/semi": "warn",
14 | "curly": "warn",
15 | "eqeqeq": "warn",
16 | "no-throw-literal": "warn",
17 | "semi": "off"
18 | },
19 | "ignorePatterns": [
20 | "out",
21 | "dist",
22 | "**/*.d.ts"
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | out
2 | dist
3 | node_modules
4 | .vscode-test/
5 | *.vsix
6 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // See http://go.microsoft.com/fwlink/?LinkId=827846
3 | // for the documentation about the extensions.json format
4 | "recommendations": ["dbaeumer.vscode-eslint", "amodio.tsl-problem-matcher"]
5 | }
6 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | // A launch configuration that compiles the extension and then opens it inside a new window
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | {
6 | "version": "0.2.0",
7 | "configurations": [
8 | {
9 | "name": "Run Extension",
10 | "type": "extensionHost",
11 | "request": "launch",
12 | "args": [
13 | "--extensionDevelopmentPath=${workspaceFolder}"
14 | ],
15 | "outFiles": [
16 | "${workspaceFolder}/dist/**/*.js"
17 | ],
18 | "preLaunchTask": "${defaultBuildTask}"
19 | },
20 | {
21 | "name": "Extension Tests",
22 | "type": "extensionHost",
23 | "request": "launch",
24 | "args": [
25 | "--extensionDevelopmentPath=${workspaceFolder}",
26 | "--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
27 | ],
28 | "outFiles": [
29 | "${workspaceFolder}/out/**/*.js",
30 | "${workspaceFolder}/dist/**/*.js"
31 | ],
32 | "preLaunchTask": "tasks: watch-tests"
33 | }
34 | ]
35 | }
36 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | // Place your settings in this file to overwrite default and user settings.
2 | {
3 | "files.exclude": {
4 | "out": false, // set this to true to hide the "out" folder with the compiled JS files
5 | "dist": false // set this to true to hide the "dist" folder with the compiled JS files
6 | },
7 | "search.exclude": {
8 | "out": true, // set this to false to include "out" folder in search results
9 | "dist": true // set this to false to include "dist" folder in search results
10 | },
11 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts
12 | "typescript.tsc.autoDetect": "off"
13 | }
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | // See https://go.microsoft.com/fwlink/?LinkId=733558
2 | // for the documentation about the tasks.json format
3 | {
4 | "version": "2.0.0",
5 | "tasks": [
6 | {
7 | "type": "npm",
8 | "script": "watch",
9 | "problemMatcher": "$ts-webpack-watch",
10 | "isBackground": true,
11 | "presentation": {
12 | "reveal": "never",
13 | "group": "watchers"
14 | },
15 | "group": {
16 | "kind": "build",
17 | "isDefault": true
18 | }
19 | },
20 | {
21 | "type": "npm",
22 | "script": "watch-tests",
23 | "problemMatcher": "$tsc-watch",
24 | "isBackground": true,
25 | "presentation": {
26 | "reveal": "never",
27 | "group": "watchers"
28 | },
29 | "group": "build"
30 | },
31 | {
32 | "label": "tasks: watch-tests",
33 | "dependsOn": [
34 | "npm: watch",
35 | "npm: watch-tests"
36 | ],
37 | "problemMatcher": []
38 | }
39 | ]
40 | }
41 |
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | .vscode/**
2 | .vscode-test/**
3 | out/**
4 | node_modules/**
5 | src/**
6 | .gitignore
7 | .yarnrc
8 | webpack.config.js
9 | vsc-extension-quickstart.md
10 | **/tsconfig.json
11 | **/.eslintrc.json
12 | **/*.map
13 | **/*.ts
14 |
--------------------------------------------------------------------------------
/.yarnrc:
--------------------------------------------------------------------------------
1 | --ignore-engines true
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to the "chatgpt" extension will be documented in this file.
4 |
5 | Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
6 |
7 | ## [Unreleased]
8 |
9 | - Initial release
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ChatGPT and GPT4 extension for VSCode
2 |
3 | [](https://marketplace.visualstudio.com/items?itemName=timkmecl.chatgpt)
4 | [](https://marketplace.visualstudio.com/items?itemName=timkmecl.chatgpt)
5 | [](https://marketplace.visualstudio.com/items?itemName=timkmecl.chatgpt)
6 | [](https://github.com/timkmecl/chatgpt-vscode)
7 |
8 | This Visual Studio Code extension allows you to use the [ChatGPT API](https://github.com/transitive-bullshit/chatgpt-api) to generate code or natural language responses from OpenAI's [ChatGPT](https://chat.openai.com/chat) or [GPT4](https://openai.com/product/gpt-4) to your questions, right within the editor.
9 |
10 | Supercharge your coding with AI-powered assistance! Automatically write new code from scratch, ask questions, get explanations, refactor code, find bugs and more 🚀✨
11 |
12 | ### Links:
13 |
14 | - **[Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=timkmecl.chatgpt)**
15 | - **[Github Repository](https://github.com/timkmecl/chatgpt-vscode)**
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | ## Features
24 | - 💡 **Ask general questions** or use code snippets from the editor to query ChatGPT via an input box in the sidebar
25 | - 🖱️ Right click on a code selection and run one of the context menu **shortcuts**
26 | - automatically write documentation for your code
27 | - explain the selected code
28 | - refactor or optimize it
29 | - find problems with it
30 | - 💻 View ChatGPT's responses in a panel next to the editor
31 | - 🚀 See the response as it is being generated **in real time**
32 | - 💬 Ask **follow-up questions** to the response (conversation context is maintained)
33 | - 📝 **Insert code snippets** from the AI's response into the active editor by clicking on them
34 |
35 |
36 |
37 | ## Setup
38 |
39 | To use this extension, install it from the VSCode marketplace.
40 |
41 | 1. After the installation is complete, you will need to add your OpenAI API key to the extension settings in VSCode. To do this, open the `Settings` panel by going to the `File` menu and selecting `Preferences`, then `Settings`.
42 | 2. In the search bar, type `ChatGPT` to filter the settings list.
43 | 3. In the ChatGPT section, enter your API key in the top field
44 |
45 | After completing these steps, the extension should be ready to use.
46 |
47 |
48 |
49 | Building from source (not applicable for VSCode marketplace version)
50 |
51 | To build the extension from source, clone the repository and run `npm install` to install the dependencies. You have to change some code in `chatgpt` module because VSCode runtime does not support `fetch`. Open `node_modules/chatgpt/dist/index.js` and add the following code at the top of the file:
52 |
53 | ```js
54 | import fetch from 'node-fetch'
55 | ```
56 |
57 | Then remove the following lines (around line 20):
58 |
59 | ```js
60 | // src/fetch.ts
61 | var fetch = globalThis.fetch;
62 | ```
63 |
64 | You also need to replace the following part near the top of the file:
65 |
66 | ```js
67 | // src/tokenizer.ts
68 | import { encoding_for_model } from "@dqbd/tiktoken";
69 | var tokenizer = encoding_for_model("text-davinci-003");
70 | function encode(input) {
71 | return tokenizer.encode(input);
72 | }
73 | ```
74 |
75 | with
76 |
77 | ```js
78 | // src/tokenizer.ts
79 | import GPT3TokenizerImport from "gpt3-tokenizer";
80 | var GPT3Tokenizer = typeof GPT3TokenizerImport === "function" ? GPT3TokenizerImport : GPT3TokenizerImport.default;
81 | var tokenizer = new GPT3Tokenizer({ type: "gpt3" });
82 | function encode(input) {
83 | return tokenizer.encode(input).bpe;
84 | }
85 | ```
86 |
87 | due to the fact that the `@dqbd/tiktoken` module is causing problems with the VSCode runtime. Delete `node_modules/@dqbd/tiktoken` directory as well. *If you know how to fix this, please let me know.*
88 |
89 | In file `node_modules/chatgpt/build/index.d.ts`, change line 1 to
90 |
91 | ```js
92 | import * as Keyv from 'keyv';
93 | ```
94 |
95 | and line 4 to
96 |
97 | ```js
98 | type FetchFn = any;
99 | ```
100 |
101 |
102 |
103 |
104 |
105 | ### Obtaining API key
106 |
107 | To use this extension, you will need an API key from OpenAI. To obtain one, follow these steps:
108 |
109 | 1. Go to [OpenAI's website](https://platform.openai.com/account/api-keys). If you don't have an account, you will need to create one or sign up using your Google or Microsoft account.
110 | 2. Click on the `Create new secret key` button.
111 | 3. Copy the key and paste it into the `API Key` field in the extension settings.
112 |
113 | ### Settings
114 |
115 | The extension can be configured or customized by changing several settings.
116 | You can choose **between ChatGPT and GPT4** by changing the `Model` setting (only if you already have access to GPT4 API). A custom API URL can also be set in the `API URL` field (probably looks something like `https://openai.xxxxxx.net/v1`, can be used to connect to a self-hosted instance of the API or a proxy).
117 |
118 |
119 |
120 |
121 | ## Using the Extension
122 |
123 | To use the extension, open a text editor in Visual Studio Code and open the ChatGPT panel by clicking on the ChatGPT icon in the sidebar. This will open a panel with an input field where you can enter your prompt or question. By clicking enter, it will be sent to ChatGPT. Its response will be displayed below the input field in the sidebar (note that it may take some time for it to be calculated).
124 |
125 |
126 |
127 | You can also select a code snippet in the editor and then enter a prompt in the side panel, or right-click and select "Ask ChatGPT". The **selected code will be automatically appended** to your query when it is sent to the AI. This can be useful for generating code snippets or getting explanations for specific pieces of code.
128 |
129 |
130 |
131 | To **insert a code snippet** from the AI's response into the editor, simply click on the code block in the panel. The code will be automatically inserted at the cursor position in the active editor.
132 |
133 |
134 |
135 | You can select some code in the editor, right click on it and choose one of the following **shortcuts** from the context menu:
136 | #### Commands:
137 | - `Ask ChatGPT`: will provide a prompt for you to enter any query
138 | - `ChatGPT: Explain selection`: will explain what the selected code does
139 | - `ChatGPT: Refactor selection`: will try to refactor the selected code
140 | - `ChatGPT: Find problems`: looks for problems/errors in the selected code, fixes and explains them
141 | - `ChatGPT: Optimize selection`: tries to optimize the selected code
142 |
143 | `Ask ChatGPT` is also available when nothing is selected. For the other four commands, you can **customize the exact prompt** that will be sent to the AI by editing the extension settings in VSCode Preferences.
144 |
145 |
146 | Because ChatGPT is a conversational AI, you can ask follow-up questions to the response. The conversation context is maintained between queries, so you can ask multiple questions in a row (this can be disabled in the extension settings.).
147 | If you aren't satisfied with an answer and would like to **retry the request**, click `ctrl+shift+p` and select `Retry ChatGPT request`. To **reset the conversation context**, click `ctrl+shift+p` and select `ChatGPT: Reset Conversation`.
148 |
149 | ---
150 |
151 | Please note that this extension is currently a proof of concept and may have some limitations or bugs. We welcome feedback and contributions to improve the extension. Also check out [CodeGPT](https://github.com/timkmecl/codegpt) extension that uses official OpenAI API and also supports other GPT3 models.
152 | If you enjoy this extension, please consider [buying me a coffee ☕️](https://www.buymeacoffee.com/timkmecl) to support my work!
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 | ## Credits
161 |
162 | - This wouldn't be possible without OpenAI's [ChatGPT](https://chat.openai.com/chat)
163 | - The extension makes use of [chatgpt-api](https://github.com/transitive-bullshit/chatgpt-api) (by [Travis Fischer](https://github.com/transitive-bullshit)), which uses unofficial ChatGPT API in order to login and communicate with it.
164 | - The project was started by [mpociot](https://github.com/mpociot/)
165 | - `v0.3` inspired by [barnesoir/chatgpt-vscode-plugin](https://github.com/barnesoir/chatgpt-vscode-plugin) and [gencay/vscode-chatgpt](https://github.com/gencay/vscode-chatgpt)
--------------------------------------------------------------------------------
/examples/create.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkmecl/chatgpt-vscode/7fc0cedf156c7298351660f4651a1b5e219ddbbe/examples/create.png
--------------------------------------------------------------------------------
/examples/explain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkmecl/chatgpt-vscode/7fc0cedf156c7298351660f4651a1b5e219ddbbe/examples/explain.png
--------------------------------------------------------------------------------
/examples/main.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkmecl/chatgpt-vscode/7fc0cedf156c7298351660f4651a1b5e219ddbbe/examples/main.png
--------------------------------------------------------------------------------
/examples/refactor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkmecl/chatgpt-vscode/7fc0cedf156c7298351660f4651a1b5e219ddbbe/examples/refactor.png
--------------------------------------------------------------------------------
/media/main.js:
--------------------------------------------------------------------------------
1 | // @ts-ignore
2 |
3 | // This script will be run within the webview itself
4 | // It cannot access the main VS Code APIs directly.
5 | (function () {
6 | const vscode = acquireVsCodeApi();
7 |
8 | let response = '';
9 |
10 | // Handle messages sent from the extension to the webview
11 | window.addEventListener("message", (event) => {
12 | const message = event.data;
13 | switch (message.type) {
14 | case "addResponse": {
15 | response = message.value;
16 | setResponse();
17 | break;
18 | }
19 | case "clearResponse": {
20 | response = '';
21 | break;
22 | }
23 | case "setPrompt": {
24 | document.getElementById("prompt-input").value = message.value;
25 | break;
26 | }
27 | }
28 | });
29 |
30 | function fixCodeBlocks(response) {
31 | // Use a regular expression to find all occurrences of the substring in the string
32 | const REGEX_CODEBLOCK = new RegExp('\`\`\`', 'g');
33 | const matches = response.match(REGEX_CODEBLOCK);
34 |
35 | // Return the number of occurrences of the substring in the response, check if even
36 | const count = matches ? matches.length : 0;
37 | if (count % 2 === 0) {
38 | return response;
39 | } else {
40 | // else append ``` to the end to make the last code block complete
41 | return response.concat('\n\`\`\`');
42 | }
43 |
44 | }
45 |
46 | function setResponse() {
47 | var converter = new showdown.Converter({
48 | omitExtraWLInCodeBlocks: true,
49 | simplifiedAutoLink: true,
50 | excludeTrailingPunctuationFromURLs: true,
51 | literalMidWordUnderscores: true,
52 | simpleLineBreaks: true
53 | });
54 | response = fixCodeBlocks(response);
55 | html = converter.makeHtml(response);
56 | document.getElementById("response").innerHTML = html;
57 |
58 | var preCodeBlocks = document.querySelectorAll("pre code");
59 | for (var i = 0; i < preCodeBlocks.length; i++) {
60 | preCodeBlocks[i].classList.add(
61 | "p-2",
62 | "my-2",
63 | "block",
64 | "overflow-x-scroll"
65 | );
66 | }
67 |
68 | var codeBlocks = document.querySelectorAll('code');
69 | for (var i = 0; i < codeBlocks.length; i++) {
70 | // Check if innertext starts with "Copy code"
71 | if (codeBlocks[i].innerText.startsWith("Copy code")) {
72 | codeBlocks[i].innerText = codeBlocks[i].innerText.replace("Copy code", "");
73 | }
74 |
75 | codeBlocks[i].classList.add("inline-flex", "max-w-full", "overflow-hidden", "rounded-sm", "cursor-pointer");
76 |
77 | codeBlocks[i].addEventListener('click', function (e) {
78 | e.preventDefault();
79 | vscode.postMessage({
80 | type: 'codeSelected',
81 | value: this.innerText
82 | });
83 | });
84 |
85 | const d = document.createElement('div');
86 | d.innerHTML = codeBlocks[i].innerHTML;
87 | codeBlocks[i].innerHTML = null;
88 | codeBlocks[i].appendChild(d);
89 | d.classList.add("code");
90 | }
91 |
92 | microlight.reset('code');
93 |
94 | //document.getElementById("response").innerHTML = document.getElementById("response").innerHTML.replaceAll('<', '<').replaceAll('>', '>');
95 | }
96 |
97 | // Listen for keyup events on the prompt input element
98 | document.getElementById('prompt-input').addEventListener('keyup', function (e) {
99 | // If the key that was pressed was the Enter key
100 | if (e.keyCode === 13) {
101 | vscode.postMessage({
102 | type: 'prompt',
103 | value: this.value
104 | });
105 | }
106 | });
107 | })();
108 |
--------------------------------------------------------------------------------
/media/scripts/microlight.min.js:
--------------------------------------------------------------------------------
1 | !function(e,t){"function"==typeof define&&define.amd?define(["exports"],t):t("undefined"!=typeof exports?exports:e.microlight={})}(this,function(e){var t,n,i,o=window,r=document,a="appendChild",l="test",c=";text-shadow:",s="opacity:.",d=" 0px 0px ",u="3px 0px 5",f=")",p=function(e){for(n=r.getElementsByClassName(e||"microlight"),t=0;i=n[t++];)for(var p,h,g,m,y,x=i.textContent,b=0,w=x[0],v=1,k=i.innerHTML="",C=0,N=/(\d*\, \d*\, \d*)(, ([.\d]*))?/g.exec(o.getComputedStyle(i).color),E="px rgba("+N[1]+",",S=N[3]||1;h=p,p=7>C&&"\\"==p?1:v;){if(v=w,w=x[++b],m=k.length>1,!v||C>8&&"\n"==v||[/\S/[l](v),1,1,!/[$\w]/[l](v),("/"==p||"\n"==p)&&m,'"'==p&&m,"'"==p&&m,x[b-4]+h+p=="-->",h+p=="*/"][C])for(k&&(i[a](y=r.createElement("span")).setAttribute("style",["",c+d+9+E+.7*S+"),"+d+2+E+.4*S+f,s+6+c+d+7+E+S/4+"),"+d+3+E+S/4+f,s+7+c+u+E+S/5+"),-"+u+E+S/5+f,"font-style:italic;"+s+5+c+u+E+S/4+"),-"+u+E+S/4+f][C?3>C?2:C>6?4:C>3?3:+/^(a(bstract|lias|nd|rguments|rray|s(m|sert)?|uto)|b(ase|egin|ool(ean)?|reak|yte)|c(ase|atch|har|hecked|lass|lone|ompl|onst|ontinue)|de(bugger|cimal|clare|f(ault|er)?|init|l(egate|ete)?)|do|double|e(cho|ls?if|lse(if)?|nd|nsure|num|vent|x(cept|ec|p(licit|ort)|te(nds|nsion|rn)))|f(allthrough|alse|inal(ly)?|ixed|loat|or(each)?|riend|rom|unc(tion)?)|global|goto|guard|i(f|mp(lements|licit|ort)|n(it|clude(_once)?|line|out|stanceof|t(erface|ernal)?)?|s)|l(ambda|et|ock|ong)|m(icrolight|odule|utable)|NaN|n(amespace|ative|ext|ew|il|ot|ull)|o(bject|perator|r|ut|verride)|p(ackage|arams|rivate|rotected|rotocol|ublic)|r(aise|e(adonly|do|f|gister|peat|quire(_once)?|scue|strict|try|turn))|s(byte|ealed|elf|hort|igned|izeof|tatic|tring|truct|ubscript|uper|ynchronized|witch)|t(emplate|hen|his|hrows?|ransient|rue|ry|ype(alias|def|id|name|of))|u(n(checked|def(ined)?|ion|less|signed|til)|se|sing)|v(ar|irtual|oid|olatile)|w(char_t|hen|here|hile|ith)|xor|yield)$/[l](k):0]),y[a](r.createTextNode(k))),g=C&&7>C?C:g,k="",C=11;![1,/[\/{}[(\-+*=<>:;|\\.,?!&@~]/[l](v),/[\])]/[l](v),/[$\w]/[l](v),"/"==v&&2>g&&"<"!=p,'"'==v,"'"==v,v+w+x[b+1]+x[b+2]=="