├── .gitignore ├── .vscode └── launch.json ├── .vscodeignore ├── LICENSE ├── README.md ├── bun.lockb ├── demo ├── aphorisms.gif ├── github-api.gif └── terminal-game.gif ├── extension.js ├── icon.png ├── package.json └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | *.vsix -------------------------------------------------------------------------------- /.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 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | node_modules/** 2 | **/*.gif -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2024 Coder Technologies Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
"
25 | }
26 | ```
27 |
28 | ## Demos
29 |
30 | _All demos are unedited._
31 |
32 | ### Creating a terminal game
33 |
34 | 
35 |
36 | ### Generating aphorisms
37 |
38 | 
39 |
40 | ### Using the GitHub API
41 |
42 | 
43 |
44 | ## Install
45 |
46 | Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
47 |
48 | ```text
49 | ext install coder.picopilot
50 | ```
51 |
52 | Feel free to configure a custom prompt in your settings.
53 |
54 | ## Development
55 |
56 | Clone the repository, run `bun install`, `bun watch`, open VS Code, and press F5 to launch the extension in development mode.
57 |
58 | Create your own AI extensions from this repo. It's remarkably simple!
59 |
--------------------------------------------------------------------------------
/bun.lockb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder/picopilot/f71c6ab4738d4159d18aa772b22f4b1d24c89899/bun.lockb
--------------------------------------------------------------------------------
/demo/aphorisms.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder/picopilot/f71c6ab4738d4159d18aa772b22f4b1d24c89899/demo/aphorisms.gif
--------------------------------------------------------------------------------
/demo/github-api.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder/picopilot/f71c6ab4738d4159d18aa772b22f4b1d24c89899/demo/github-api.gif
--------------------------------------------------------------------------------
/demo/terminal-game.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder/picopilot/f71c6ab4738d4159d18aa772b22f4b1d24c89899/demo/terminal-game.gif
--------------------------------------------------------------------------------
/extension.js:
--------------------------------------------------------------------------------
1 | const vscode = require("vscode");
2 | const OpenAI = require("openai");
3 |
4 | module.exports = {
5 | activate: (ctx) => {
6 | let api;
7 | const initAPI = async () => {
8 | api = new OpenAI({ apiKey: await ctx.secrets.get("openai-key") });
9 | };
10 | initAPI();
11 | ctx.secrets.onDidChange((event) => {
12 | if (event.key === "openai-key") initAPI();
13 | });
14 | vscode.languages.registerInlineCompletionItemProvider(
15 | { pattern: "**" },
16 | {
17 | provideInlineCompletionItems: async (document, position) => {
18 | if (!api) {
19 | const res = await vscode.window.showErrorMessage(
20 | "You must configure an OpenAI API Key!",
21 | "Set Key"
22 | );
23 | if (res)
24 | await vscode.commands.executeCommand("picopilot.token");
25 | return;
26 | }
27 | const prefix = document.getText(new vscode.Range(new vscode.Position(0, 0), position));
28 | const suffix = document.getText(new vscode.Range(position, document.positionAt(document.getText().length)));
29 | const prompt =
30 | vscode.workspace.getConfiguration("picopilot").get("prompt") || `You provide code completion results given a prefix and suffix.
31 | Respond with a JSON object with the key 'completion' containing a suggestion to place between the prefix and suffix.
32 | Follow existing code styles. Listen to comments at the end of the prefix. The language is "{language}".`;
33 |
34 | const response = await api.chat.completions.create({
35 | messages: [
36 | {
37 | role: "system",
38 | content: prompt.replace("{language}", document.languageId),
39 | },
40 | { role: "user", content: prefix },
41 | { role: "user", content: suffix },
42 | ],
43 | model: "gpt-4o",
44 | max_tokens: 500,
45 | response_format: { type: "json_object" },
46 | });
47 | const resp = JSON.parse(response.choices[0].message.content);
48 | return {
49 | items: [{ insertText: resp.completion.trim() }],
50 | };
51 | },
52 | }
53 | );
54 | vscode.commands.registerCommand("picopilot.token", async () => {
55 | await vscode.env.openExternal(
56 | vscode.Uri.parse("https://platform.openai.com/api-keys")
57 | );
58 | const res = await vscode.window.showInputBox({
59 | title: "OpenAI API Key",
60 | prompt: "Generate an API Key and paste it in!",
61 | ignoreFocusOut: true,
62 | password: true,
63 | });
64 | if (res) {
65 | await ctx.secrets.store("openai-key", res);
66 | vscode.window.showInformationMessage("PicoPilot is working!");
67 | initAPI();
68 | }
69 | });
70 | },
71 | };
72 |
--------------------------------------------------------------------------------
/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coder/picopilot/f71c6ab4738d4159d18aa772b22f4b1d24c89899/icon.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "picopilot",
3 | "publisher": "coder",
4 | "displayName": "Picopilot",
5 | "description": "GitHub Copilot in 70 lines of JavaScript.",
6 | "repository": {
7 | "url": "https://github.com/coder/picopilot"
8 | },
9 | "version": "1.0.3",
10 | "engines": {
11 | "vscode": "^1.90.0"
12 | },
13 | "categories": [
14 | "Programming Languages",
15 | "Machine Learning",
16 | "AI"
17 | ],
18 | "activationEvents": [
19 | "*"
20 | ],
21 | "icon": "./icon.png",
22 | "main": "./dist/extension.js",
23 | "contributes": {
24 | "commands": [
25 | {
26 | "command": "picopilot.token",
27 | "title": "Picopilot: Set OpenAI API Key"
28 | }
29 | ],
30 | "configuration":[
31 | {
32 | "title": "Picopilot",
33 | "properties": {
34 | "picopilot.prompt": {
35 | "type": "string",
36 | "default": "",
37 | "description": "The prompt to use to generate completions. '{language}' is replaced with the active document language."
38 | }
39 | }
40 | }
41 | ]
42 | },
43 | "scripts": {
44 | "build": "webpack --mode production --devtool hidden-source-map",
45 | "watch": "bun run build -- --watch",
46 | "package": "vsce package --allow-star-activation"
47 | },
48 | "devDependencies": {
49 | "@types/vscode": "^1.90.0",
50 | "webpack": "^5.92.1",
51 | "webpack-cli": "^5.1.4"
52 | },
53 | "dependencies": {
54 | "openai": "^4.52.0"
55 | }
56 | }
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | //@ts-check
2 |
3 | "use strict";
4 |
5 | const path = require("path");
6 |
7 | //@ts-check
8 | /** @typedef {import('webpack').Configuration} WebpackConfig **/
9 |
10 | /** @type WebpackConfig */
11 | const extensionConfig = {
12 | target: "node", // VS Code extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/
13 | mode: "none", // this leaves the source code as close as possible to the original (when packaging we set this to 'production')
14 |
15 | entry: "./extension.js", // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
16 | output: {
17 | // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
18 | path: path.resolve(__dirname, "dist"),
19 | filename: "extension.js",
20 | libraryTarget: "commonjs2",
21 | },
22 | externals: {
23 | vscode: "commonjs vscode",
24 | },
25 | resolve: {
26 | extensions: [".js"],
27 | },
28 | devtool: "nosources-source-map",
29 | };
30 | module.exports = [extensionConfig];
31 |
--------------------------------------------------------------------------------