From f53768612b1e2268697b5444e502032ef9f3fb3c Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Tue, 23 May 2023 23:45:12 -0400 Subject: copying from old repo --- extension/media/spinner.gif | Bin 0 -> 43034 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 extension/media/spinner.gif (limited to 'extension/media') diff --git a/extension/media/spinner.gif b/extension/media/spinner.gif new file mode 100644 index 00000000..61cd2c0f Binary files /dev/null and b/extension/media/spinner.gif differ -- cgit v1.2.3-70-g09d2 From 36522ad6551bfcc51b1e923e7d50dfca1af1c697 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Sat, 27 May 2023 18:35:21 -0400 Subject: esbuild and preparing for publishing --- extension/.vscodeignore | 1 + extension/LICENSE.txt | 18 +- extension/README.md | 33 +- extension/media/continue-gradient.png | Bin 0 -> 13218 bytes extension/package-lock.json | 578 +++++++++++++++++++++++++++++++++- extension/package.json | 36 +-- 6 files changed, 614 insertions(+), 52 deletions(-) create mode 100644 extension/media/continue-gradient.png (limited to 'extension/media') diff --git a/extension/.vscodeignore b/extension/.vscodeignore index 8fddc39a..f65d24a9 100644 --- a/extension/.vscodeignore +++ b/extension/.vscodeignore @@ -1,5 +1,6 @@ .vscode/** .vscode-test/** +build/** src/** .gitignore .yarnrc diff --git a/extension/LICENSE.txt b/extension/LICENSE.txt index eddcb4e6..a12f2a75 100644 --- a/extension/LICENSE.txt +++ b/extension/LICENSE.txt @@ -1,5 +1,13 @@ -/******************************************************* - * Copyright (C) 2023 Continue - * - * All rights reserved. - *******************************************************/ \ No newline at end of file +Copyright 2023 Continue + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/extension/README.md b/extension/README.md index 0a003145..55cf25d1 100644 --- a/extension/README.md +++ b/extension/README.md @@ -1,36 +1,17 @@ -# continue +# Continue -Bug report to fix in 1/10th the time. +Automate software development at the level of tasks, instead of tab-autocompletions. With Continue, you can make large edits with natural language, ask questions of your codebase, and run custom recipes built with our open-source Python library. -Our debugging assistant automatically handles tedious portions of the debugging process, such as: - -- Fault localization -- Enumerating potential error sources -- Generating fixes -- Pulling in outside context -- Following data flows -- Parsing tracebacks -- Generate unit tests -- Generate docstrings +Get started by opening the command pallet with `cmd+shift+p` and then selecting `Continue: Open Debug Panel`. # Features ### Ask a Question -`cmd+shift+j` to open up a universal search bar, where you can ask questions of your codebase in natural language. - -### Fault Localization - -Either manually highlight code snippets you think are suspicious, or let us find them for you. - -### Generate a Fix - -Once Continue has code snippets to work with, it can generate a fix. Just click to accept or reject, or make the tweak you need. - -### Stacktrace Parsing +Ask natural language questions of your codebase, like "Where is the entry point to the VS Code extension?" -Any stacktrace that appears in your VSCode terminal will be caught by us so we can immediately begin the debugging process. For small bugs that you might have quickly solved, we'll just speed up the process to be nearly instantaneous. +### Edit with Natural Language -### Generate Unit Tests and Docstrings +Request an edit to the currently open file, for example: "Add CORS headers to this FastAPI server". -Use `cmd+shift+i` to generate a unit test for the function surrounding your cursor position, and `cmd+shift+l` to generate a docstring. +### Generate Unit Tests diff --git a/extension/media/continue-gradient.png b/extension/media/continue-gradient.png new file mode 100644 index 00000000..2b382040 Binary files /dev/null and b/extension/media/continue-gradient.png differ diff --git a/extension/package-lock.json b/extension/package-lock.json index c8907210..a90827d8 100644 --- a/extension/package-lock.json +++ b/extension/package-lock.json @@ -1,12 +1,12 @@ { "name": "continue", - "version": "0.0.1", + "version": "0.0.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "continue", - "version": "0.0.1", + "version": "0.0.2", "dependencies": { "@electron/rebuild": "^3.2.10", "@reduxjs/toolkit": "^1.9.3", @@ -30,6 +30,7 @@ "@typescript-eslint/eslint-plugin": "^5.45.0", "@typescript-eslint/parser": "^5.45.0", "@vscode/test-electron": "^2.2.0", + "esbuild": "^0.17.19", "eslint": "^8.28.0", "glob": "^8.0.3", "json-schema-to-typescript": "^12.0.0", @@ -451,6 +452,358 @@ "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==", "peer": true }, + "node_modules/@esbuild/android-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", + "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz", + "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz", + "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz", + "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz", + "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz", + "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz", + "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz", + "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz", + "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz", + "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz", + "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz", + "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz", + "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz", + "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz", + "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", + "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz", + "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz", + "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz", + "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz", + "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz", + "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz", + "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint/eslintrc": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", @@ -3217,6 +3570,43 @@ "es6-symbol": "^3.1.1" } }, + "node_modules/esbuild": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz", + "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.17.19", + "@esbuild/android-arm64": "0.17.19", + "@esbuild/android-x64": "0.17.19", + "@esbuild/darwin-arm64": "0.17.19", + "@esbuild/darwin-x64": "0.17.19", + "@esbuild/freebsd-arm64": "0.17.19", + "@esbuild/freebsd-x64": "0.17.19", + "@esbuild/linux-arm": "0.17.19", + "@esbuild/linux-arm64": "0.17.19", + "@esbuild/linux-ia32": "0.17.19", + "@esbuild/linux-loong64": "0.17.19", + "@esbuild/linux-mips64el": "0.17.19", + "@esbuild/linux-ppc64": "0.17.19", + "@esbuild/linux-riscv64": "0.17.19", + "@esbuild/linux-s390x": "0.17.19", + "@esbuild/linux-x64": "0.17.19", + "@esbuild/netbsd-x64": "0.17.19", + "@esbuild/openbsd-x64": "0.17.19", + "@esbuild/sunos-x64": "0.17.19", + "@esbuild/win32-arm64": "0.17.19", + "@esbuild/win32-ia32": "0.17.19", + "@esbuild/win32-x64": "0.17.19" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -7734,6 +8124,160 @@ "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==", "peer": true }, + "@esbuild/android-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", + "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz", + "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz", + "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz", + "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz", + "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz", + "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz", + "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz", + "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz", + "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz", + "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz", + "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz", + "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz", + "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz", + "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz", + "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", + "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz", + "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz", + "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz", + "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz", + "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz", + "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz", + "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==", + "dev": true, + "optional": true + }, "@eslint/eslintrc": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", @@ -9817,6 +10361,36 @@ "es6-symbol": "^3.1.1" } }, + "esbuild": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz", + "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.17.19", + "@esbuild/android-arm64": "0.17.19", + "@esbuild/android-x64": "0.17.19", + "@esbuild/darwin-arm64": "0.17.19", + "@esbuild/darwin-x64": "0.17.19", + "@esbuild/freebsd-arm64": "0.17.19", + "@esbuild/freebsd-x64": "0.17.19", + "@esbuild/linux-arm": "0.17.19", + "@esbuild/linux-arm64": "0.17.19", + "@esbuild/linux-ia32": "0.17.19", + "@esbuild/linux-loong64": "0.17.19", + "@esbuild/linux-mips64el": "0.17.19", + "@esbuild/linux-ppc64": "0.17.19", + "@esbuild/linux-riscv64": "0.17.19", + "@esbuild/linux-s390x": "0.17.19", + "@esbuild/linux-x64": "0.17.19", + "@esbuild/netbsd-x64": "0.17.19", + "@esbuild/openbsd-x64": "0.17.19", + "@esbuild/sunos-x64": "0.17.19", + "@esbuild/win32-arm64": "0.17.19", + "@esbuild/win32-ia32": "0.17.19", + "@esbuild/win32-x64": "0.17.19" + } + }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", diff --git a/extension/package.json b/extension/package.json index 3f9e59ff..525ec075 100644 --- a/extension/package.json +++ b/extension/package.json @@ -1,12 +1,20 @@ { "name": "continue", + "icon": "media/continue-gradient.png", "repository": { "type": "git", - "url": "" + "url": "https://github.com/continuedev/continue" }, + "bugs": { + "url": "https://github.com/continuedev/continue/issues", + "email": "nate@continue.dev" + }, + "homepage": "https://continue.dev", + "license": "Apache-2.0", "displayName": "Continue", - "description": "Reduce debugging time by 10x", - "version": "0.0.1", + "pricing": "Free", + "description": "Refine code 10x faster", + "version": "0.0.2", "publisher": "Continue", "engines": { "vscode": "^1.74.0" @@ -107,21 +115,6 @@ } ], "keybindings": [ - { - "command": "continue.writeDocstring", - "key": "ctrl+alt+l", - "mac": "shift+cmd+l" - }, - { - "command": "continue.writeUnitTest", - "key": "ctrl+alt+i", - "mac": "shift+cmd+i" - }, - { - "command": "continue.askQuestionFromInput", - "key": "ctrl+alt+j", - "mac": "shift+cmd+j" - }, { "command": "continue.suggestionDown", "mac": "shift+ctrl+down", @@ -154,9 +147,13 @@ } }, "scripts": { + "vscode:prepublish": "npm run esbuild-base -- --minify", + "esbuild-base": "esbuild ./src/extension.ts --bundle --outfile=out/extension.js --external:vscode --format=cjs --platform=node", + "esbuild": "npm run esbuild-base -- --sourcemap", + "esbuild-watch": "npm run esbuild-base -- --sourcemap --watch", + "test-compile": "tsc -p ./", "clientgen": "rm -rf src/client/ && npx @openapitools/openapi-generator-cli generate -i ../schema/openapi.json -g typescript-fetch -o src/client/ --additional-properties=supportsES6=true,npmVersion=8.19.2,typescriptThreePlus=true", "typegen": "node scripts/typegen.js", - "vscode:prepublish": "npm run compile", "rebuild": "electron-rebuild -v 19.1.8 node-pty", "compile": "tsc -p ./", "watch": "tsc -watch -p ./", @@ -179,6 +176,7 @@ "@typescript-eslint/eslint-plugin": "^5.45.0", "@typescript-eslint/parser": "^5.45.0", "@vscode/test-electron": "^2.2.0", + "esbuild": "^0.17.19", "eslint": "^8.28.0", "glob": "^8.0.3", "json-schema-to-typescript": "^12.0.0", -- cgit v1.2.3-70-g09d2 From 43dc3459997d79d112a2776a8e95546580112460 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Thu, 29 Jun 2023 09:51:24 -0700 Subject: messaging of welcome step --- extension/media/walkthrough.md | 1 + extension/package-lock.json | 4 ++-- extension/package.json | 2 +- extension/react-app/src/tabs/gui.tsx | 28 ++++++++++++++++++++++------ extension/src/activation/environmentSetup.ts | 9 ++++----- extension/src/continueIdeClient.ts | 15 ++++++++++++--- extension/src/util/messenger.ts | 8 ++++++++ 7 files changed, 50 insertions(+), 17 deletions(-) create mode 100644 extension/media/walkthrough.md (limited to 'extension/media') diff --git a/extension/media/walkthrough.md b/extension/media/walkthrough.md new file mode 100644 index 00000000..fe77a69a --- /dev/null +++ b/extension/media/walkthrough.md @@ -0,0 +1 @@ +# Welcome to Continue diff --git a/extension/package-lock.json b/extension/package-lock.json index 241ea5ca..c33567c4 100644 --- a/extension/package-lock.json +++ b/extension/package-lock.json @@ -1,12 +1,12 @@ { "name": "continue", - "version": "0.0.86", + "version": "0.0.88", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "continue", - "version": "0.0.86", + "version": "0.0.88", "license": "Apache-2.0", "dependencies": { "@electron/rebuild": "^3.2.10", diff --git a/extension/package.json b/extension/package.json index 7eca6042..e34af438 100644 --- a/extension/package.json +++ b/extension/package.json @@ -14,7 +14,7 @@ "displayName": "Continue", "pricing": "Free", "description": "Accelerating software development with language models", - "version": "0.0.86", + "version": "0.0.88", "publisher": "Continue", "engines": { "vscode": "^1.74.0" diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx index 249d9785..8d21a457 100644 --- a/extension/react-app/src/tabs/gui.tsx +++ b/extension/react-app/src/tabs/gui.tsx @@ -63,7 +63,12 @@ function GUI(props: GUIProps) { >([]); const [dataSwitchChecked, setDataSwitchChecked] = useState(false); const [showDataSharingInfo, setShowDataSharingInfo] = useState(false); - const [stepsOpen, setStepsOpen] = useState([]); + const [stepsOpen, setStepsOpen] = useState([ + true, + true, + true, + true, + ]); const [history, setHistory] = useState({ timeline: [ { @@ -78,13 +83,24 @@ function GUI(props: GUIProps) { { name: "Welcome to Continue", hide: false, - description: - "Type '/' to see the list of available slash commands. If you highlight code, edits and explanations will be localized to the highlighted range. Otherwise, the currently open file is used. In both cases, the code is combined with the previous steps to construct the context.", + description: `Welcome to Continue`, system_message: null, chat_context: [], manage_own_chat_context: false, - message: - "Type '/' to see the list of available slash commands. If you highlight code, edits and explanations will be localized to the highlighted range. Otherwise, the currently open file is used. In both cases, the code is combined with the previous steps to construct the context.", + message: `# Welcome to Continue + + _If it's your first time using Continue, it can take up to a minute for the server to install._ + + Continue is not perfect, but a great tool to add to your toolbox. These are the tasks that Continue is currently best at: + + - Highlight a section of code and instruct Continue to refactor it, e.g. \`"/edit make this use more descriptive variable names"\` + - Ask questions of the open file, e.g. \`"/explain what is the purpose of each of these if statements?"\` + - Ask Continue to build the scaffolding of a new file from scratch, e.g. \`"add a React component for syntax highlighted code"\` + + You can use "slash commands" to directly instruct Continue what to do, or just enter a request and it will automatically decide next steps. To see the list of available slash commands, type '/'. + + If you highlight code, edits and explanations will be localized to the highlighted range. Otherwise, the currently open file is used. In both cases, the code is combined with the previous steps to construct the context. + `, }, { name: "Welcome to Continue!", @@ -585,7 +601,7 @@ function GUI(props: GUIProps) { onClick={() => { client?.sendClear(); }} - text="Clear All" + text="Clear" > diff --git a/extension/src/activation/environmentSetup.ts b/extension/src/activation/environmentSetup.ts index 823670fd..b8c23733 100644 --- a/extension/src/activation/environmentSetup.ts +++ b/extension/src/activation/environmentSetup.ts @@ -150,11 +150,10 @@ async function setupPythonEnv() { // Repeat until it is successfully created (sometimes it fails to generate the bin, need to try again) while (true) { const [, stderr] = await runCommand(createEnvCommand); - if (stderr) { - throw new Error(stderr); - } if (checkEnvExists()) { break; + } else if (stderr) { + throw new Error(stderr); } else { // Remove the env and try again const removeCommand = `rm -rf "${path.join( @@ -180,7 +179,6 @@ async function setupPythonEnv() { activateCmd, pipUpgradeCmd, `${pipCmd} install -r requirements.txt`, - touchCmd, ].join(" ; "); const [, stderr] = await runCommand(installRequirementsCommand); if (stderr) { @@ -273,13 +271,14 @@ export async function startContinuePythonServer() { console.log(`stdout: ${data}`); }); child.stderr.on("data", (data: any) => { - console.log(`stderr: ${data}`); if ( data.includes("Uvicorn running on") || // Successfully started the server data.includes("address already in use") // The server is already running (probably a simultaneously opened VS Code window) ) { console.log("Successfully started Continue python server"); resolve(null); + } else { + console.log(`stderr: ${data}`); } }); child.on("error", (error: any) => { diff --git a/extension/src/continueIdeClient.ts b/extension/src/continueIdeClient.ts index 8ab3e075..d983d93a 100644 --- a/extension/src/continueIdeClient.ts +++ b/extension/src/continueIdeClient.ts @@ -226,9 +226,18 @@ class IdeProtocolClient { } async getSessionId(): Promise { - if (this.messenger === null) { - console.log("MESSENGER IS NULL"); - } + await new Promise((resolve, reject) => { + // Repeatedly try to connect to the server + const interval = setInterval(() => { + if ( + this.messenger && + this.messenger.websocket.readyState === 1 // 1 => OPEN + ) { + clearInterval(interval); + resolve(null); + } + }, 1000); + }); const resp = await this.messenger?.sendAndReceive("openGUI", {}); const sessionId = resp.sessionId; console.log("New Continue session with ID: ", sessionId); diff --git a/extension/src/util/messenger.ts b/extension/src/util/messenger.ts index 6f8bb29d..e4133230 100644 --- a/extension/src/util/messenger.ts +++ b/extension/src/util/messenger.ts @@ -54,6 +54,14 @@ export class WebsocketMessenger extends Messenger { super(); this.serverUrl = serverUrl; this.websocket = this._newWebsocket(); + + const interval = setInterval(() => { + if (this.websocket.readyState === this.websocket.OPEN) { + clearInterval(interval); + } else if (this.websocket.readyState !== this.websocket.CONNECTING) { + this.websocket = this._newWebsocket(); + } + }, 1000); } send(messageType: string, data: object) { -- cgit v1.2.3-70-g09d2 From bd433511695f7a7b2291243841a6366ba33b0f35 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Thu, 29 Jun 2023 14:53:27 -0700 Subject: new continue logo --- extension/media/continue-gradient.png | Bin 13218 -> 14449 bytes 1 file changed, 0 insertions(+), 0 deletions(-) (limited to 'extension/media') diff --git a/extension/media/continue-gradient.png b/extension/media/continue-gradient.png index 2b382040..f5458877 100644 Binary files a/extension/media/continue-gradient.png and b/extension/media/continue-gradient.png differ -- cgit v1.2.3-70-g09d2 From a5a342a14073777439d09dc70c0079860333e042 Mon Sep 17 00:00:00 2001 From: Ty Dunn Date: Thu, 29 Jun 2023 23:14:13 -0700 Subject: initial walkthrough --- extension/media/edit.png | Bin 0 -> 246984 bytes extension/media/explain.png | Bin 0 -> 464952 bytes extension/media/generate.png | Bin 0 -> 1049613 bytes extension/package.json | 37 ++++++++++++++----------------------- 4 files changed, 14 insertions(+), 23 deletions(-) create mode 100644 extension/media/edit.png create mode 100644 extension/media/explain.png create mode 100644 extension/media/generate.png (limited to 'extension/media') diff --git a/extension/media/edit.png b/extension/media/edit.png new file mode 100644 index 00000000..5e77c0ea Binary files /dev/null and b/extension/media/edit.png differ diff --git a/extension/media/explain.png b/extension/media/explain.png new file mode 100644 index 00000000..196ab914 Binary files /dev/null and b/extension/media/explain.png differ diff --git a/extension/media/generate.png b/extension/media/generate.png new file mode 100644 index 00000000..9d84e4ae Binary files /dev/null and b/extension/media/generate.png differ diff --git a/extension/package.json b/extension/package.json index 9d0ef3ac..b2db62e2 100644 --- a/extension/package.json +++ b/extension/package.json @@ -159,45 +159,36 @@ "walkthroughs": [ { "id": "continue", - "title": "Getting Started with Continue", - "description": "Learn how to effectively use Continue", + "title": "Getting Started", + "description": "Learn how to use Continue", "steps": [ { "id": "edit", - "title": "Highlight and Edit", - "description": "This step will run a command and check off once it has been run.\n[Run Command](command:getting-started-sample.runCommand)", + "title": "Edit in natural language", + "description": "Highlight a section of code and instruct Continue to refactor it (e.g. `/edit Make this use more descriptive variable names`)", "media": { - "image": "media/image.png", + "image": "media/edit.png", "altText": "Empty image" }, - "completionEvents": [ - "onCommand:continue.acceptSuggestion" - ] + "completionEvents": [] }, { "id": "explain", - "title": "Ask Questions", - "description": "This step will change a setting and check off when the setting has changed\n[Change Setting](command:getting-started-sample.changeSetting)", + "title": "Get possible explanations", + "description": "Ask Continue about a part of your code to get another perspective (e.g. `/explain how do I find running process on port 8000?`)", "media": { - "markdown": "media/walkthrough.md" + "image": "media/explain.png", + "altText": "Empty image" }, "completionEvents": [] }, { "id": "generate", - "title": "Generate Files from Scratch", - "description": "Ask Continue to create a file from scratch.", - "media": { - "markdown": "media/walkthrough.md" - }, - "completionEvents": [] - }, - { - "id": "commands", - "title": "Use a Slash Command", - "description": "Highlight some code then type '/explain' followed by a question. Slash commands let you select exactly the function you'd like Continue to perform. Others include '/edit' (to edit code), '/comment' (to comment code), and '/feedback' (to share with us what you think of Continue).", + "title": "Generate files from scratch", + "description": "Let Continue build the scaffolding of Python scripts, React components, and more (e.g. `Create a shell script to back up my home dir to /tmp/`)", "media": { - "markdown": "media/walkthrough.md" + "image": "media/generate.png", + "altText": "Empty image" }, "completionEvents": [] } -- cgit v1.2.3-70-g09d2 From 5c03dd4775845c559a1f6298f7577609ba907bb1 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Wed, 5 Jul 2023 23:49:37 -0700 Subject: ui overhaul --- continuedev/src/continuedev/core/autopilot.py | 47 +++- continuedev/src/continuedev/core/main.py | 9 +- .../src/continuedev/models/generate_json_schema.py | 4 +- continuedev/src/continuedev/server/gui.py | 14 + .../media/Lexend/Lexend-VariableFont_wght.ttf | Bin 0 -> 176220 bytes extension/media/Lexend/OFL.txt | 93 +++++++ extension/media/Lexend/README.txt | 71 +++++ extension/media/Lexend/static/Lexend-Black.ttf | Bin 0 -> 78496 bytes extension/media/Lexend/static/Lexend-Bold.ttf | Bin 0 -> 78632 bytes extension/media/Lexend/static/Lexend-ExtraBold.ttf | Bin 0 -> 78716 bytes .../media/Lexend/static/Lexend-ExtraLight.ttf | Bin 0 -> 78508 bytes extension/media/Lexend/static/Lexend-Light.ttf | Bin 0 -> 78668 bytes extension/media/Lexend/static/Lexend-Medium.ttf | Bin 0 -> 78696 bytes extension/media/Lexend/static/Lexend-Regular.ttf | Bin 0 -> 78360 bytes extension/media/Lexend/static/Lexend-SemiBold.ttf | Bin 0 -> 78744 bytes extension/media/Lexend/static/Lexend-Thin.ttf | Bin 0 -> 78380 bytes extension/react-app/package-lock.json | 59 ++++ extension/react-app/package.json | 1 + extension/react-app/src/App.tsx | 39 +-- extension/react-app/src/components/CodeBlock.tsx | 4 +- extension/react-app/src/components/ComboBox.tsx | 191 +++++++------ .../react-app/src/components/ContinueButton.tsx | 2 +- .../src/components/HeaderButtonWithText.tsx | 44 +-- extension/react-app/src/components/Loader.tsx | 40 +++ extension/react-app/src/components/PillButton.tsx | 144 +++++++--- .../react-app/src/components/StepContainer.tsx | 13 +- extension/react-app/src/components/TextDialog.tsx | 2 +- .../src/components/UserInputContainer.tsx | 6 +- extension/react-app/src/components/index.ts | 22 +- .../src/hooks/ContinueGUIClientProtocol.ts | 4 + .../react-app/src/hooks/useContinueGUIProtocol.ts | 8 + extension/react-app/src/index.css | 9 +- extension/react-app/src/main.tsx | 6 +- extension/react-app/src/tabs/gui.tsx | 22 +- extension/schema/FullState.d.ts | 133 +++++++++ extension/src/debugPanel.ts | 4 + schema/json/FullState.json | 304 +++++++++++++++++++++ 37 files changed, 1088 insertions(+), 207 deletions(-) create mode 100644 extension/media/Lexend/Lexend-VariableFont_wght.ttf create mode 100644 extension/media/Lexend/OFL.txt create mode 100644 extension/media/Lexend/README.txt create mode 100644 extension/media/Lexend/static/Lexend-Black.ttf create mode 100644 extension/media/Lexend/static/Lexend-Bold.ttf create mode 100644 extension/media/Lexend/static/Lexend-ExtraBold.ttf create mode 100644 extension/media/Lexend/static/Lexend-ExtraLight.ttf create mode 100644 extension/media/Lexend/static/Lexend-Light.ttf create mode 100644 extension/media/Lexend/static/Lexend-Medium.ttf create mode 100644 extension/media/Lexend/static/Lexend-Regular.ttf create mode 100644 extension/media/Lexend/static/Lexend-SemiBold.ttf create mode 100644 extension/media/Lexend/static/Lexend-Thin.ttf create mode 100644 extension/react-app/src/components/Loader.tsx create mode 100644 extension/schema/FullState.d.ts create mode 100644 schema/json/FullState.json (limited to 'extension/media') diff --git a/continuedev/src/continuedev/core/autopilot.py b/continuedev/src/continuedev/core/autopilot.py index b1c4f471..acdc1f0d 100644 --- a/continuedev/src/continuedev/core/autopilot.py +++ b/continuedev/src/continuedev/core/autopilot.py @@ -12,7 +12,7 @@ from .observation import Observation, InternalErrorObservation from ..server.ide_protocol import AbstractIdeProtocolServer from ..libs.util.queue import AsyncSubscriptionQueue from ..models.main import ContinueBaseModel -from .main import Context, ContinueCustomException, Policy, History, FullState, Step, HistoryNode +from .main import Context, ContinueCustomException, HighlightedRangeContext, Policy, History, FullState, Step, HistoryNode from ..steps.core.core import ReversibleStep, ManualEditStep, UserInputStep from ..libs.util.telemetry import capture_event from .sdk import ContinueSDK @@ -140,11 +140,24 @@ class Autopilot(ContinueBaseModel): tb_step.step_name, {"output": output, **tb_step.params}) await self._run_singular_step(step) - _highlighted_ranges: List[RangeInFileWithContents] = [] + _highlighted_ranges: List[HighlightedRangeContext] = [] _adding_highlighted_code: bool = False + def _make_sure_is_editing_range(self): + """If none of the highlighted ranges are currently being edited, the first should be selected""" + if len(self._highlighted_ranges) == 0: + return + if not any(map(lambda x: x.editing, self._highlighted_ranges)): + self._highlighted_ranges[0].editing = True + async def handle_highlighted_code(self, range_in_files: List[RangeInFileWithContents]): - if not self._adding_highlighted_code: + if not self._adding_highlighted_code and len(self._highlighted_ranges) > 0: + return + + # If un-highlighting, then remove the range + if len(self._highlighted_ranges) == 1 and len(range_in_files) == 1 and range_in_files[0].range.start == range_in_files[0].range.end: + self._highlighted_ranges = [] + await self.update_subscribers() return # Filter out rifs from ~/.continue/diffs folder @@ -160,20 +173,25 @@ class Autopilot(ContinueBaseModel): for i, rif in enumerate(self._highlighted_ranges): found_overlap = False for new_rif in range_in_files: - if rif.filepath == new_rif.filepath and rif.range.overlaps_with(new_rif.range): + if rif.range.filepath == new_rif.filepath and rif.range.range.overlaps_with(new_rif.range): found_overlap = True break # Also don't allow multiple ranges in same file with same content. This is useless to the model, and avoids # the bug where cmd+f causes repeated highlights - if rif.filepath == new_rif.filepath and rif.contents == new_rif.contents: + if rif.range.filepath == new_rif.filepath and rif.range.contents == new_rif.contents: found_overlap = True break if not found_overlap: new_ranges.append(rif) - self._highlighted_ranges = new_ranges + range_in_files + self._highlighted_ranges = new_ranges + [HighlightedRangeContext( + range=rif, editing=False, pinned=False + ) for rif in range_in_files] + + self._make_sure_is_editing_range() + await self.update_subscribers() _step_depth: int = 0 @@ -193,12 +211,25 @@ class Autopilot(ContinueBaseModel): if i not in indices: kept_ranges.append(rif) self._highlighted_ranges = kept_ranges + + self._make_sure_is_editing_range() + await self.update_subscribers() async def toggle_adding_highlighted_code(self): self._adding_highlighted_code = not self._adding_highlighted_code await self.update_subscribers() + async def set_editing_at_indices(self, indices: List[int]): + for i in range(len(self._highlighted_ranges)): + self._highlighted_ranges[i].editing = i in indices + await self.update_subscribers() + + async def set_pinned_at_indices(self, indices: List[int]): + for i in range(len(self._highlighted_ranges)): + self._highlighted_ranges[i].pinned = i in indices + await self.update_subscribers() + async def _run_singular_step(self, step: "Step", is_future_step: bool = False) -> Coroutine[Observation, None, None]: # Allow config to set disallowed steps if step.__class__.__name__ in self.continue_sdk.config.disallowed_steps: @@ -359,6 +390,10 @@ class Autopilot(ContinueBaseModel): if len(self._main_user_input_queue) > 1: return + # Remove context unless pinned + self._highlighted_ranges = [ + hr for hr in self._highlighted_ranges if hr.pinned] + # await self._request_halt() # Just run the step that takes user input, and # then up to the policy to decide how to deal with it. diff --git a/continuedev/src/continuedev/core/main.py b/continuedev/src/continuedev/core/main.py index 28fd964e..62cc4936 100644 --- a/continuedev/src/continuedev/core/main.py +++ b/continuedev/src/continuedev/core/main.py @@ -199,13 +199,20 @@ class SlashCommandDescription(ContinueBaseModel): description: str +class HighlightedRangeContext(ContinueBaseModel): + """Context for a highlighted range""" + range: RangeInFileWithContents + editing: bool + pinned: bool + + class FullState(ContinueBaseModel): """A full state of the program, including the history""" history: History active: bool user_input_queue: List[str] default_model: str - highlighted_ranges: List[RangeInFileWithContents] + highlighted_ranges: List[HighlightedRangeContext] slash_commands: List[SlashCommandDescription] adding_highlighted_code: bool diff --git a/continuedev/src/continuedev/models/generate_json_schema.py b/continuedev/src/continuedev/models/generate_json_schema.py index 080787a5..6cebf429 100644 --- a/continuedev/src/continuedev/models/generate_json_schema.py +++ b/continuedev/src/continuedev/models/generate_json_schema.py @@ -1,7 +1,7 @@ from .main import * from .filesystem import RangeInFile, FileEdit from .filesystem_edit import FileEditWithFullContents -from ..core.main import History, HistoryNode +from ..core.main import History, HistoryNode, FullState from pydantic import schema_json_of import os @@ -12,7 +12,7 @@ MODELS_TO_GENERATE = [ ] + [ FileEditWithFullContents ] + [ - History, HistoryNode + History, HistoryNode, FullState ] RENAMES = { diff --git a/continuedev/src/continuedev/server/gui.py b/continuedev/src/continuedev/server/gui.py index fa573b37..8e9b1fb9 100644 --- a/continuedev/src/continuedev/server/gui.py +++ b/continuedev/src/continuedev/server/gui.py @@ -87,6 +87,10 @@ class GUIProtocolServer(AbstractGUIProtocolServer): self.on_delete_context_at_indices(data["indices"]) elif message_type == "toggle_adding_highlighted_code": self.on_toggle_adding_highlighted_code() + elif message_type == "set_editing_at_indices": + self.on_set_editing_at_indices(data["indices"]) + elif message_type == "set_pinned_at_indices": + self.on_set_pinned_at_indices(data["indices"]) except Exception as e: print(e) @@ -135,6 +139,16 @@ class GUIProtocolServer(AbstractGUIProtocolServer): self.session.autopilot.toggle_adding_highlighted_code() ) + def on_set_editing_at_indices(self, indices: List[int]): + asyncio.create_task( + self.session.autopilot.set_editing_at_indices(indices) + ) + + def on_set_pinned_at_indices(self, indices: List[int]): + asyncio.create_task( + self.session.autopilot.set_pinned_at_indices(indices) + ) + @router.websocket("/ws") async def websocket_endpoint(websocket: WebSocket, session: Session = Depends(websocket_session)): diff --git a/extension/media/Lexend/Lexend-VariableFont_wght.ttf b/extension/media/Lexend/Lexend-VariableFont_wght.ttf new file mode 100644 index 00000000..b294dc84 Binary files /dev/null and b/extension/media/Lexend/Lexend-VariableFont_wght.ttf differ diff --git a/extension/media/Lexend/OFL.txt b/extension/media/Lexend/OFL.txt new file mode 100644 index 00000000..6b679248 --- /dev/null +++ b/extension/media/Lexend/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2018 The Lexend Project Authors (https://github.com/googlefonts/lexend), with Reserved Font Name “RevReading Lexend”. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/extension/media/Lexend/README.txt b/extension/media/Lexend/README.txt new file mode 100644 index 00000000..f2966dfe --- /dev/null +++ b/extension/media/Lexend/README.txt @@ -0,0 +1,71 @@ +Lexend Variable Font +==================== + +This download contains Lexend as both a variable font and static fonts. + +Lexend is a variable font with this axis: + wght + +This means all the styles are contained in a single file: + Lexend-VariableFont_wght.ttf + +If your app fully supports variable fonts, you can now pick intermediate styles +that aren’t available as static fonts. Not all apps support variable fonts, and +in those cases you can use the static font files for Lexend: + static/Lexend-Thin.ttf + static/Lexend-ExtraLight.ttf + static/Lexend-Light.ttf + static/Lexend-Regular.ttf + static/Lexend-Medium.ttf + static/Lexend-SemiBold.ttf + static/Lexend-Bold.ttf + static/Lexend-ExtraBold.ttf + static/Lexend-Black.ttf + +Get started +----------- + +1. Install the font files you want to use + +2. Use your app's font picker to view the font family and all the +available styles + +Learn more about variable fonts +------------------------------- + + https://developers.google.com/web/fundamentals/design-and-ux/typography/variable-fonts + https://variablefonts.typenetwork.com + https://medium.com/variable-fonts + +In desktop apps + + https://theblog.adobe.com/can-variable-fonts-illustrator-cc + https://helpx.adobe.com/nz/photoshop/using/fonts.html#variable_fonts + +Online + + https://developers.google.com/fonts/docs/getting_started + https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide + https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/variable-fonts + +Installing fonts + + MacOS: https://support.apple.com/en-us/HT201749 + Linux: https://www.google.com/search?q=how+to+install+a+font+on+gnu%2Blinux + Windows: https://support.microsoft.com/en-us/help/314960/how-to-install-or-remove-a-font-in-windows + +Android Apps + + https://developers.google.com/fonts/docs/android + https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts + +License +------- +Please read the full license text (OFL.txt) to understand the permissions, +restrictions and requirements for usage, redistribution, and modification. + +You can use them in your products & projects – print or digital, +commercial or otherwise. + +This isn't legal advice, please consider consulting a lawyer and see the full +license for all details. diff --git a/extension/media/Lexend/static/Lexend-Black.ttf b/extension/media/Lexend/static/Lexend-Black.ttf new file mode 100644 index 00000000..2fea087c Binary files /dev/null and b/extension/media/Lexend/static/Lexend-Black.ttf differ diff --git a/extension/media/Lexend/static/Lexend-Bold.ttf b/extension/media/Lexend/static/Lexend-Bold.ttf new file mode 100644 index 00000000..95884f6e Binary files /dev/null and b/extension/media/Lexend/static/Lexend-Bold.ttf differ diff --git a/extension/media/Lexend/static/Lexend-ExtraBold.ttf b/extension/media/Lexend/static/Lexend-ExtraBold.ttf new file mode 100644 index 00000000..02f84ed3 Binary files /dev/null and b/extension/media/Lexend/static/Lexend-ExtraBold.ttf differ diff --git a/extension/media/Lexend/static/Lexend-ExtraLight.ttf b/extension/media/Lexend/static/Lexend-ExtraLight.ttf new file mode 100644 index 00000000..20e7068d Binary files /dev/null and b/extension/media/Lexend/static/Lexend-ExtraLight.ttf differ diff --git a/extension/media/Lexend/static/Lexend-Light.ttf b/extension/media/Lexend/static/Lexend-Light.ttf new file mode 100644 index 00000000..fb6d097c Binary files /dev/null and b/extension/media/Lexend/static/Lexend-Light.ttf differ diff --git a/extension/media/Lexend/static/Lexend-Medium.ttf b/extension/media/Lexend/static/Lexend-Medium.ttf new file mode 100644 index 00000000..d91a8673 Binary files /dev/null and b/extension/media/Lexend/static/Lexend-Medium.ttf differ diff --git a/extension/media/Lexend/static/Lexend-Regular.ttf b/extension/media/Lexend/static/Lexend-Regular.ttf new file mode 100644 index 00000000..b423d3ab Binary files /dev/null and b/extension/media/Lexend/static/Lexend-Regular.ttf differ diff --git a/extension/media/Lexend/static/Lexend-SemiBold.ttf b/extension/media/Lexend/static/Lexend-SemiBold.ttf new file mode 100644 index 00000000..9dcb8214 Binary files /dev/null and b/extension/media/Lexend/static/Lexend-SemiBold.ttf differ diff --git a/extension/media/Lexend/static/Lexend-Thin.ttf b/extension/media/Lexend/static/Lexend-Thin.ttf new file mode 100644 index 00000000..0d7df881 Binary files /dev/null and b/extension/media/Lexend/static/Lexend-Thin.ttf differ diff --git a/extension/react-app/package-lock.json b/extension/react-app/package-lock.json index fb13dffd..7316581d 100644 --- a/extension/react-app/package-lock.json +++ b/extension/react-app/package-lock.json @@ -20,6 +20,7 @@ "react-redux": "^8.0.5", "react-switch": "^7.0.0", "react-syntax-highlighter": "^15.5.0", + "react-tooltip": "^5.18.0", "styled-components": "^5.3.6", "vscode-webview": "^1.0.1-beta.1" }, @@ -597,6 +598,19 @@ "node": ">=12" } }, + "node_modules/@floating-ui/core": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.3.1.tgz", + "integrity": "sha512-Bu+AMaXNjrpjh41znzHqaz3r2Nr8hHuHZT6V2LBKMhyMl0FgKA62PNYbqnfgmzOhoWZj70Zecisbo4H1rotP5g==" + }, + "node_modules/@floating-ui/dom": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.4.4.tgz", + "integrity": "sha512-21hhDEPOiWkGp0Ys4Wi6Neriah7HweToKra626CIK712B5m9qkdz54OP9gVldUg+URnBTpv/j/bi/skmGdstXQ==", + "dependencies": { + "@floating-ui/core": "^1.3.1" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", @@ -1310,6 +1324,11 @@ "node": ">= 6" } }, + "node_modules/classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -2967,6 +2986,19 @@ "react": ">= 0.14.0" } }, + "node_modules/react-tooltip": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.18.0.tgz", + "integrity": "sha512-qjDK/skUJJ27sc9lTWeNxp2rLzmenBTskSsRiDOCPnupGSz2GhL5IZxDizK/sOsk0hn5iSCywt+3jKxUJ3Y4Sw==", + "dependencies": { + "@floating-ui/dom": "^1.0.0", + "classnames": "^2.3.0" + }, + "peerDependencies": { + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -3886,6 +3918,19 @@ "dev": true, "optional": true }, + "@floating-ui/core": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.3.1.tgz", + "integrity": "sha512-Bu+AMaXNjrpjh41znzHqaz3r2Nr8hHuHZT6V2LBKMhyMl0FgKA62PNYbqnfgmzOhoWZj70Zecisbo4H1rotP5g==" + }, + "@floating-ui/dom": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.4.4.tgz", + "integrity": "sha512-21hhDEPOiWkGp0Ys4Wi6Neriah7HweToKra626CIK712B5m9qkdz54OP9gVldUg+URnBTpv/j/bi/skmGdstXQ==", + "requires": { + "@floating-ui/core": "^1.3.1" + } + }, "@jridgewell/gen-mapping": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", @@ -4350,6 +4395,11 @@ } } }, + "classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -5411,6 +5461,15 @@ "refractor": "^3.6.0" } }, + "react-tooltip": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.18.0.tgz", + "integrity": "sha512-qjDK/skUJJ27sc9lTWeNxp2rLzmenBTskSsRiDOCPnupGSz2GhL5IZxDizK/sOsk0hn5iSCywt+3jKxUJ3Y4Sw==", + "requires": { + "@floating-ui/dom": "^1.0.0", + "classnames": "^2.3.0" + } + }, "read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", diff --git a/extension/react-app/package.json b/extension/react-app/package.json index 12701906..4bedb813 100644 --- a/extension/react-app/package.json +++ b/extension/react-app/package.json @@ -21,6 +21,7 @@ "react-redux": "^8.0.5", "react-switch": "^7.0.0", "react-syntax-highlighter": "^15.5.0", + "react-tooltip": "^5.18.0", "styled-components": "^5.3.6", "vscode-webview": "^1.0.1-beta.1" }, diff --git a/extension/react-app/src/App.tsx b/extension/react-app/src/App.tsx index a51541d0..8785f88f 100644 --- a/extension/react-app/src/App.tsx +++ b/extension/react-app/src/App.tsx @@ -1,28 +1,33 @@ import DebugPanel from "./components/DebugPanel"; import MainTab from "./tabs/main"; -import { Provider } from "react-redux"; -import store from "./redux/store"; import WelcomeTab from "./tabs/welcome"; import ChatTab from "./tabs/chat"; import GUI from "./tabs/gui"; +import { createContext } from "react"; +import useContinueGUIProtocol from "./hooks/useWebsocket"; +import ContinueGUIClientProtocol from "./hooks/useContinueGUIProtocol"; + +export const GUIClientContext = createContext< + ContinueGUIClientProtocol | undefined +>(undefined); function App() { + const client = useContinueGUIProtocol(); + return ( - <> - - , - title: "GUI", - }, - // { element: , title: "Debug Panel" }, - // { element: , title: "Welcome" }, - // { element: , title: "Chat" }, - ]} - > - - + + , + title: "GUI", + }, + // { element: , title: "Debug Panel" }, + // { element: , title: "Welcome" }, + // { element: , title: "Chat" }, + ]} + /> + ); } diff --git a/extension/react-app/src/components/CodeBlock.tsx b/extension/react-app/src/components/CodeBlock.tsx index 17f5626b..fe9b3a95 100644 --- a/extension/react-app/src/components/CodeBlock.tsx +++ b/extension/react-app/src/components/CodeBlock.tsx @@ -52,9 +52,9 @@ function CopyButton(props: { textToCopy: string; visible: boolean }) { }} > {clicked ? ( - + ) : ( - + )} diff --git a/extension/react-app/src/components/ComboBox.tsx b/extension/react-app/src/components/ComboBox.tsx index 81b148b9..7ee5dc24 100644 --- a/extension/react-app/src/components/ComboBox.tsx +++ b/extension/react-app/src/components/ComboBox.tsx @@ -4,6 +4,7 @@ import styled from "styled-components"; import { buttonColor, defaultBorderRadius, + lightGray, secondaryDark, vscBackground, } from "."; @@ -16,11 +17,32 @@ import { LockClosed, LockOpen, Plus, + DocumentPlus, } from "@styled-icons/heroicons-outline"; +import { HighlightedRangeContext } from "../../../schema/FullState"; // #region styled components const mainInputFontSize = 16; +const EmptyPillDiv = styled.div` + padding: 8px; + border-radius: ${defaultBorderRadius}; + border: 1px dashed ${lightGray}; + color: ${lightGray}; + background-color: ${vscBackground}; + overflow: hidden; + display: flex; + align-items: center; + text-align: center; + cursor: pointer; + font-size: 13px; + + &:hover { + background-color: ${lightGray}; + color: ${vscBackground}; + } +`; + const ContextDropdown = styled.div` position: absolute; padding: 4px; @@ -41,17 +63,19 @@ const MainTextInput = styled.textarea` padding: 8px; font-size: ${mainInputFontSize}px; + font-family: inherit; + border: 1px solid transparent; border-radius: ${defaultBorderRadius}; - border: 1px solid white; margin: 8px auto; + height: auto; width: 100%; - background-color: ${vscBackground}; + background-color: ${secondaryDark}; color: white; z-index: 1; &:focus { + outline: 1px solid #ff000066; border: 1px solid transparent; - outline: 1px solid orange; } `; @@ -69,7 +93,6 @@ const Ul = styled.ul<{ background: ${vscBackground}; background-color: ${secondaryDark}; color: white; - font-family: "Fira Code", monospace; max-height: ${UlMaxHeight}px; overflow: scroll; padding: 0; @@ -102,7 +125,7 @@ interface ComboBoxProps { onInputValueChange: (inputValue: string) => void; disabled?: boolean; onEnter: (e: React.KeyboardEvent) => void; - highlightedCodeSections: (RangeInFile & { contents: string })[]; + highlightedCodeSections: HighlightedRangeContext[]; deleteContextItems: (indices: number[]) => void; onTogglePin: () => void; onToggleAddContext: () => void; @@ -119,16 +142,7 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => { React.useState(false); const [pinned, setPinned] = useState(false); const [highlightedCodeSections, setHighlightedCodeSections] = React.useState( - props.highlightedCodeSections || [ - { - filepath: "test.ts", - range: { - start: { line: 0, character: 0 }, - end: { line: 0, character: 0 }, - }, - contents: "import * as a from 'a';", - }, - ] + props.highlightedCodeSections || [] ); useEffect(() => { @@ -169,6 +183,71 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => { return ( <> +
+ {highlightedCodeSections.length > 1 && ( + <> + { + props.deleteContextItems( + highlightedCodeSections.map((_, idx) => idx) + ); + }} + > + + + + )} + {highlightedCodeSections.map((section, idx) => ( + { + if (props.deleteContextItems) { + props.deleteContextItems([idx]); + } + setHighlightedCodeSections((prev) => { + const newSections = [...prev]; + newSections.splice(idx, 1); + return newSections; + }); + }} + onHover={(val: boolean) => { + if (val) { + setHoveringButton(val); + } else { + setTimeout(() => { + setHoveringButton(val); + }, 100); + } + }} + /> + ))} + {props.highlightedCodeSections.length > 0 && + (props.addingHighlightedCode ? ( + { + props.onToggleAddContext(); + }} + > + Highlight to Add Context + + ) : ( + { + props.onToggleAddContext(); + }} + > + + + ))} +
-
- {highlightedCodeSections.length === 0 && ( - { - props.onToggleAddContext(); - }} - inverted={props.addingHighlightedCode} - > - - - )} - {highlightedCodeSections.length > 0 && ( - <> - { - props.deleteContextItems( - highlightedCodeSections.map((_, idx) => idx) - ); - }} - > - - - { - setPinned((prev) => !prev); - props.onTogglePin(); - }} - > - {pinned ? ( - - ) : ( - - )} - - - )} - {highlightedCodeSections.map((section, idx) => ( - { - if (props.deleteContextItems) { - props.deleteContextItems([idx]); - } - setHighlightedCodeSections((prev) => { - const newSections = [...prev]; - newSections.splice(idx, 1); - return newSections; - }); - }} - onHover={(val: boolean) => { - if (val) { - setHoveringButton(val); - } else { - setTimeout(() => { - setHoveringButton(val); - }, 100); - } - }} - /> - ))} - - - Highlight code to include as context. Currently open file included by - default. {highlightedCodeSections.length === 0 && ""} - -
+ {/* + Highlight code to include as context. Currently open file included by + default. {highlightedCodeSections.length === 0 && ""} + */} { setHoveringContextDropdown(true); @@ -345,9 +354,9 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => { > {highlightedCodeSections.map((section, idx) => ( <> -

{section.filepath}

+

{section.range.filepath}

- {section.contents} + {section.range.contents} ))} diff --git a/extension/react-app/src/components/ContinueButton.tsx b/extension/react-app/src/components/ContinueButton.tsx index 5295799a..462f2b46 100644 --- a/extension/react-app/src/components/ContinueButton.tsx +++ b/extension/react-app/src/components/ContinueButton.tsx @@ -18,7 +18,7 @@ let StyledButton = styled(Button)` &:hover { transition-delay: 0.5s; - transition-property: background; + transition-property: "background"; background: linear-gradient( 45deg, #be1a55 14.44%, diff --git a/extension/react-app/src/components/HeaderButtonWithText.tsx b/extension/react-app/src/components/HeaderButtonWithText.tsx index 72a653c5..de8e3c98 100644 --- a/extension/react-app/src/components/HeaderButtonWithText.tsx +++ b/extension/react-app/src/components/HeaderButtonWithText.tsx @@ -1,6 +1,7 @@ import React, { useState } from "react"; - -import { HeaderButton } from "."; +import { Tooltip } from "react-tooltip"; +import styled from "styled-components"; +import { HeaderButton, StyledTooltip, defaultBorderRadius } from "."; interface HeaderButtonWithTextProps { text: string; @@ -13,25 +14,28 @@ interface HeaderButtonWithTextProps { const HeaderButtonWithText = (props: HeaderButtonWithTextProps) => { const [hover, setHover] = useState(false); - const paddingLeft = (props.disabled ? (props.active ? "3px" : "1px"): (hover ? "4px" : "1px")); return ( - { - if (!props.disabled) { - setHover(true); - } - }} - onMouseLeave={() => { - setHover(false); - }} - onClick={props.onClick} - > - - {props.children} - + <> + { + if (!props.disabled) { + setHover(true); + } + }} + onMouseLeave={() => { + setHover(false); + }} + onClick={props.onClick} + > + {props.children} + + + {props.text} + + ); }; diff --git a/extension/react-app/src/components/Loader.tsx b/extension/react-app/src/components/Loader.tsx new file mode 100644 index 00000000..90eff793 --- /dev/null +++ b/extension/react-app/src/components/Loader.tsx @@ -0,0 +1,40 @@ +import { Play } from "@styled-icons/heroicons-outline"; +import { useSelector } from "react-redux"; +import styled from "styled-components"; +import { RootStore } from "../redux/store"; + +const DEFAULT_SIZE = "28px"; + +const FlashingDiv = styled.div` + margin: auto; + width: ${DEFAULT_SIZE}; + animation: flash 1.2s infinite ease-in-out; + @keyframes flash { + 0% { + opacity: 0.4; + } + 50% { + opacity: 1; + } + 100% { + opacity: 0.4; + } + } +`; + +function Loader(props: { size?: string }) { + const vscMediaUrl = useSelector( + (state: RootStore) => state.config.vscMediaUrl + ); + return ( + + {vscMediaUrl ? ( + + ) : ( + + )} + + ); +} + +export default Loader; diff --git a/extension/react-app/src/components/PillButton.tsx b/extension/react-app/src/components/PillButton.tsx index 5a02c6b2..a384832e 100644 --- a/extension/react-app/src/components/PillButton.tsx +++ b/extension/react-app/src/components/PillButton.tsx @@ -1,54 +1,136 @@ -import { useState } from "react"; +import { useContext, useState } from "react"; import styled from "styled-components"; -import { defaultBorderRadius } from "."; -import { XMark } from "@styled-icons/heroicons-outline"; +import { + StyledTooltip, + defaultBorderRadius, + lightGray, + secondaryDark, +} from "."; +import { Trash, PaintBrush, MapPin } from "@styled-icons/heroicons-outline"; +import { GUIClientContext } from "../App"; const Button = styled.button` border: none; color: white; - background-color: transparent; - border: 1px solid white; + background-color: ${secondaryDark}; border-radius: ${defaultBorderRadius}; - padding: 3px 6px; + padding: 8px; + overflow: hidden; + + cursor: pointer; +`; + +const GridDiv = styled.div` + position: absolute; + left: 0px; + top: 0px; + width: 100%; + height: 100%; + display: grid; + grid-gap: 0; + grid-template-columns: 1fr 1fr; + align-items: center; + border-radius: ${defaultBorderRadius}; + overflow: hidden; + + background-color: ${secondaryDark}; +`; + +const ButtonDiv = styled.div<{ backgroundColor: string }>` + background-color: ${secondaryDark}; + padding: 3px; + height: 100%; + display: flex; + align-items: center; &:hover { - background-color: white; - color: black; + background-color: ${(props) => props.backgroundColor}; } - - cursor: pointer; `; interface PillButtonProps { onHover?: (arg0: boolean) => void; onDelete?: () => void; title: string; + index: number; + editing: boolean; + pinned: boolean; } const PillButton = (props: PillButtonProps) => { const [isHovered, setIsHovered] = useState(false); + const client = useContext(GUIClientContext); + return ( - + <> + + + {props.editing ? "Editing this range" : "Edit this range"} + + Delete + ); }; diff --git a/extension/react-app/src/components/StepContainer.tsx b/extension/react-app/src/components/StepContainer.tsx index 2aed2e72..91d7b8ef 100644 --- a/extension/react-app/src/components/StepContainer.tsx +++ b/extension/react-app/src/components/StepContainer.tsx @@ -13,7 +13,7 @@ import { ArrowPath, XMark, } from "@styled-icons/heroicons-outline"; -import { Stop } from "@styled-icons/heroicons-solid"; +import { StopCircle } from "@styled-icons/heroicons-solid"; import { HistoryNode } from "../../../schema/HistoryNode"; import ReactMarkdown from "react-markdown"; import HeaderButtonWithText from "./HeaderButtonWithText"; @@ -67,7 +67,6 @@ const HeaderDiv = styled.div<{ error: boolean; loading: boolean }>` const ContentDiv = styled.div<{ isUserInput: boolean }>` padding: 8px; - padding-left: 16px; background-color: ${(props) => props.isUserInput ? secondaryDark : vscBackground}; font-size: 13px; @@ -167,7 +166,7 @@ function StepContainer(props: StepContainerProps) { ? "#f00" : props.historyNode.active ? undefined - : "white" + : "transparent" } className="overflow-hidden cursor-pointer" onClick={(e) => { @@ -182,7 +181,7 @@ function StepContainer(props: StepContainerProps) { loading={props.historyNode.active as boolean | false} error={props.historyNode.observation?.error ? true : false} > -

+
{!isUserInput && (props.open ? ( @@ -191,7 +190,7 @@ function StepContainer(props: StepContainerProps) { ))} {props.historyNode.observation?.title || (props.historyNode.step.name as any)} -

+ {/* { e.stopPropagation(); @@ -203,16 +202,14 @@ function StepContainer(props: StepContainerProps) { <> { e.stopPropagation(); props.onDelete(); }} text={props.historyNode.active ? "Stop" : "Delete"} - active={props.historyNode.active} > {props.historyNode.active ? ( - + ) : ( )} diff --git a/extension/react-app/src/components/TextDialog.tsx b/extension/react-app/src/components/TextDialog.tsx index a564f884..ea5727f0 100644 --- a/extension/react-app/src/components/TextDialog.tsx +++ b/extension/react-app/src/components/TextDialog.tsx @@ -8,6 +8,7 @@ const ScreenCover = styled.div` width: 100%; height: 100%; background-color: rgba(168, 168, 168, 0.5); + z-index: 100; `; const DialogContainer = styled.div` @@ -35,7 +36,6 @@ const TextArea = styled.textarea` border-radius: 8px; padding: 8px; outline: 1px solid black; - font-family: Arial, Helvetica, sans-serif; resize: none; &:focus { diff --git a/extension/react-app/src/components/UserInputContainer.tsx b/extension/react-app/src/components/UserInputContainer.tsx index 28437d35..f51f0cb5 100644 --- a/extension/react-app/src/components/UserInputContainer.tsx +++ b/extension/react-app/src/components/UserInputContainer.tsx @@ -15,12 +15,10 @@ interface UserInputContainerProps { } const StyledDiv = styled.div` - background-color: rgb(45 45 45); + background-color: ${secondaryDark}; padding: 8px; padding-left: 16px; padding-right: 16px; - border-bottom: 1px solid white; - border-top: 1px solid white; font-size: 13px; display: flex; align-items: center; @@ -29,7 +27,7 @@ const StyledDiv = styled.div` const UserInputContainer = (props: UserInputContainerProps) => { return ( - {props.children} + {props.children}
{ diff --git a/extension/react-app/src/components/index.ts b/extension/react-app/src/components/index.ts index db1925ed..9ae0f097 100644 --- a/extension/react-app/src/components/index.ts +++ b/extension/react-app/src/components/index.ts @@ -1,7 +1,9 @@ +import { Tooltip } from "react-tooltip"; import styled, { keyframes } from "styled-components"; export const defaultBorderRadius = "5px"; -export const secondaryDark = "rgb(42 42 42)"; +export const lightGray = "rgb(100 100 100)"; +export const secondaryDark = "rgb(45 45 45)"; export const vscBackground = "rgb(30 30 30)"; export const vscBackgroundTransparent = "#1e1e1ede"; export const buttonColor = "rgb(113 28 59)"; @@ -26,6 +28,16 @@ export const Button = styled.button` } `; +export const StyledTooltip = styled(Tooltip)` + font-size: 12px; + background-color: rgb(60 60 60); + border-radius: ${defaultBorderRadius}; + padding: 6px; + padding-left: 12px; + padding-right: 12px; + z-index: 100; +`; + export const TextArea = styled.textarea` width: 100%; border-radius: ${defaultBorderRadius}; @@ -128,19 +140,17 @@ export const HeaderButton = styled.button<{ inverted: boolean | undefined }>` background-color: ${({ inverted }) => (inverted ? "white" : "transparent")}; color: ${({ inverted }) => (inverted ? "black" : "white")}; - border: 1px solid white; + border: none; border-radius: ${defaultBorderRadius}; cursor: pointer; &:hover { background-color: ${({ inverted }) => - typeof inverted === "undefined" || inverted ? "white" : "transparent"}; - color: ${({ inverted }) => - typeof inverted === "undefined" || inverted ? "black" : "white"}; + typeof inverted === "undefined" || inverted ? lightGray : "transparent"}; } display: flex; align-items: center; justify-content: center; gap: 4px; - padding: 1px; + padding: 2px; `; diff --git a/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts b/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts index f123bb2b..a179c2bf 100644 --- a/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts +++ b/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts @@ -23,6 +23,10 @@ abstract class AbstractContinueGUIClientProtocol { abstract deleteContextAtIndices(indices: number[]): void; + abstract setEditingAtIndices(indices: number[]): void; + + abstract setPinnedAtIndices(indices: number[]): void; + abstract toggleAddingHighlightedCode(): void; } diff --git a/extension/react-app/src/hooks/useContinueGUIProtocol.ts b/extension/react-app/src/hooks/useContinueGUIProtocol.ts index 49f200ae..2060dd7f 100644 --- a/extension/react-app/src/hooks/useContinueGUIProtocol.ts +++ b/extension/react-app/src/hooks/useContinueGUIProtocol.ts @@ -75,6 +75,14 @@ class ContinueGUIClientProtocol extends AbstractContinueGUIClientProtocol { this.messenger.send("delete_context_at_indices", { indices }); } + setEditingAtIndices(indices: number[]) { + this.messenger.send("set_editing_at_indices", { indices }); + } + + setPinnedAtIndices(indices: number[]) { + this.messenger.send("set_pinned_at_indices", { indices }); + } + toggleAddingHighlightedCode(): void { this.messenger.send("toggle_adding_highlighted_code", {}); } diff --git a/extension/react-app/src/index.css b/extension/react-app/src/index.css index 6dc514ec..682551f8 100644 --- a/extension/react-app/src/index.css +++ b/extension/react-app/src/index.css @@ -10,19 +10,12 @@ --def-border-radius: 5px; } -@font-face { - font-family: "Mona Sans"; - src: url("assets/Mona-Sans.woff2") format("woff2 supports variations"), - url("assets/Mona-Sans.woff2") format("woff2-variations"); - font-weight: 200 900; - font-stretch: 75% 85%; -} - html, body, #root { height: 100%; background-color: var(--vsc-background); + font-family: "Lexend", sans-serif; } body { diff --git a/extension/react-app/src/main.tsx b/extension/react-app/src/main.tsx index 0b02575c..a76bced6 100644 --- a/extension/react-app/src/main.tsx +++ b/extension/react-app/src/main.tsx @@ -1,6 +1,8 @@ import React from "react"; import ReactDOM from "react-dom/client"; import App from "./App"; +import { Provider } from "react-redux"; +import store from "./redux/store"; import "./index.css"; import posthog from "posthog-js"; @@ -17,7 +19,9 @@ posthog.init("phc_JS6XFROuNbhJtVCEdTSYk6gl5ArRrTNMpCcguAXlSPs", { ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( - + + + ); diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx index e5320c6a..3cce30de 100644 --- a/extension/react-app/src/tabs/gui.tsx +++ b/extension/react-app/src/tabs/gui.tsx @@ -1,11 +1,13 @@ import styled from "styled-components"; -import { defaultBorderRadius, Loader } from "../components"; +import { defaultBorderRadius } from "../components"; +import Loader from "../components/Loader"; import ContinueButton from "../components/ContinueButton"; -import { useCallback, useEffect, useRef, useState } from "react"; +import { FullState, HighlightedRangeContext } from "../../../schema/FullState"; +import { useCallback, useEffect, useRef, useState, useContext } from "react"; import { History } from "../../../schema/History"; import { HistoryNode } from "../../../schema/HistoryNode"; import StepContainer from "../components/StepContainer"; -import useContinueGUIProtocol from "../hooks/useWebsocket"; +import { GUIClientContext } from "../App"; import { BookOpen, ChatBubbleOvalLeftEllipsis, @@ -52,6 +54,7 @@ interface GUIProps { } function GUI(props: GUIProps) { + const client = useContext(GUIClientContext); const posthog = usePostHog(); const vscMachineId = useSelector( (state: RootStore) => state.config.vscMachineId @@ -70,7 +73,9 @@ function GUI(props: GUIProps) { const [usingFastModel, setUsingFastModel] = useState(false); const [waitingForSteps, setWaitingForSteps] = useState(false); const [userInputQueue, setUserInputQueue] = useState([]); - const [highlightedRanges, setHighlightedRanges] = useState([]); + const [highlightedRanges, setHighlightedRanges] = useState< + HighlightedRangeContext[] + >([]); const [addingHighlightedCode, setAddingHighlightedCode] = useState(false); const [availableSlashCommands, setAvailableSlashCommands] = useState< { name: string; description: string }[] @@ -112,7 +117,6 @@ function GUI(props: GUIProps) { const [feedbackDialogMessage, setFeedbackDialogMessage] = useState(""); const topGuiDivRef = useRef(null); - const client = useContinueGUIProtocol(); const [scrollTimeout, setScrollTimeout] = useState( null @@ -148,7 +152,7 @@ function GUI(props: GUIProps) { }, []); useEffect(() => { - client?.onStateUpdate((state) => { + client?.onStateUpdate((state: FullState) => { // Scroll only if user is at very bottom of the window. setUsingFastModel(state.default_model === "gpt-3.5-turbo"); const shouldScrollToBottom = @@ -289,7 +293,7 @@ function GUI(props: GUIProps) { > {typeof client === "undefined" && ( <> - +

Loading Continue server...

)} @@ -316,7 +320,8 @@ function GUI(props: GUIProps) { setStepsOpen(nextStepsOpen); }} onToggleAll={() => { - setStepsOpen((prev) => prev.map((_, index) => !prev[index])); + const shouldOpen = !stepsOpen[index]; + setStepsOpen((prev) => prev.map(() => shouldOpen)); }} key={index} onUserInput={(input: string) => { @@ -381,6 +386,7 @@ function GUI(props: GUIProps) { borderRadius: defaultBorderRadius, padding: "16px", margin: "16px", + zIndex: 100, }} hidden={!showDataSharingInfo} > diff --git a/extension/schema/FullState.d.ts b/extension/schema/FullState.d.ts new file mode 100644 index 00000000..981e772e --- /dev/null +++ b/extension/schema/FullState.d.ts @@ -0,0 +1,133 @@ +/* eslint-disable */ +/** + * This file was automatically generated by json-schema-to-typescript. + * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, + * and run json-schema-to-typescript to regenerate this file. + */ + +export type FullState = FullState1; +export type Name = string; +export type Hide = boolean; +export type Description = string; +export type SystemMessage = string; +export type Role = "assistant" | "user" | "system" | "function"; +export type Content = string; +export type Name1 = string; +export type Summary = string; +export type Name2 = string; +export type Arguments = string; +export type ChatContext = ChatMessage[]; +export type ManageOwnChatContext = boolean; +export type Depth = number; +export type Deleted = boolean; +export type Active = boolean; +export type Timeline = HistoryNode[]; +export type CurrentIndex = number; +export type Active1 = boolean; +export type UserInputQueue = string[]; +export type DefaultModel = string; +export type Filepath = string; +export type Line = number; +export type Character = number; +export type Contents = string; +export type Editing = boolean; +export type Pinned = boolean; +export type HighlightedRanges = HighlightedRangeContext[]; +export type Name3 = string; +export type Description1 = string; +export type SlashCommands = SlashCommandDescription[]; +export type AddingHighlightedCode = boolean; + +/** + * A full state of the program, including the history + */ +export interface FullState1 { + history: History; + active: Active1; + user_input_queue: UserInputQueue; + default_model: DefaultModel; + highlighted_ranges: HighlightedRanges; + slash_commands: SlashCommands; + adding_highlighted_code: AddingHighlightedCode; + [k: string]: unknown; +} +/** + * A history of steps taken and their results + */ +export interface History { + timeline: Timeline; + current_index: CurrentIndex; + [k: string]: unknown; +} +/** + * A point in history, a list of which make up History + */ +export interface HistoryNode { + step: Step; + observation?: Observation; + depth: Depth; + deleted?: Deleted; + active?: Active; + [k: string]: unknown; +} +export interface Step { + name?: Name; + hide?: Hide; + description?: Description; + system_message?: SystemMessage; + chat_context?: ChatContext; + manage_own_chat_context?: ManageOwnChatContext; + [k: string]: unknown; +} +export interface ChatMessage { + role: Role; + content?: Content; + name?: Name1; + summary: Summary; + function_call?: FunctionCall; + [k: string]: unknown; +} +export interface FunctionCall { + name: Name2; + arguments: Arguments; + [k: string]: unknown; +} +export interface Observation { + [k: string]: unknown; +} +/** + * Context for a highlighted range + */ +export interface HighlightedRangeContext { + range: RangeInFileWithContents; + editing: Editing; + pinned: Pinned; + [k: string]: unknown; +} +/** + * A range in a file with the contents of the range. + */ +export interface RangeInFileWithContents { + filepath: Filepath; + range: Range; + contents: Contents; + [k: string]: unknown; +} +/** + * A range in a file. 0-indexed. + */ +export interface Range { + start: Position; + end: Position; + [k: string]: unknown; +} +export interface Position { + line: Line; + character: Character; + [k: string]: unknown; +} +export interface SlashCommandDescription { + name: Name3; + description: Description1; + [k: string]: unknown; +} diff --git a/extension/src/debugPanel.ts b/extension/src/debugPanel.ts index b88c86f3..487bbedf 100644 --- a/extension/src/debugPanel.ts +++ b/extension/src/debugPanel.ts @@ -341,6 +341,10 @@ export function setupDebugPanel( + + + + Continue diff --git a/schema/json/FullState.json b/schema/json/FullState.json new file mode 100644 index 00000000..af0f25e1 --- /dev/null +++ b/schema/json/FullState.json @@ -0,0 +1,304 @@ +{ + "title": "FullState", + "$ref": "#/definitions/src__continuedev__core__main__FullState", + "definitions": { + "FunctionCall": { + "title": "FunctionCall", + "type": "object", + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "arguments": { + "title": "Arguments", + "type": "string" + } + }, + "required": [ + "name", + "arguments" + ] + }, + "ChatMessage": { + "title": "ChatMessage", + "type": "object", + "properties": { + "role": { + "title": "Role", + "enum": [ + "assistant", + "user", + "system", + "function" + ], + "type": "string" + }, + "content": { + "title": "Content", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "summary": { + "title": "Summary", + "type": "string" + }, + "function_call": { + "$ref": "#/definitions/FunctionCall" + } + }, + "required": [ + "role", + "summary" + ] + }, + "Step": { + "title": "Step", + "type": "object", + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "hide": { + "title": "Hide", + "default": false, + "type": "boolean" + }, + "description": { + "title": "Description", + "type": "string" + }, + "system_message": { + "title": "System Message", + "type": "string" + }, + "chat_context": { + "title": "Chat Context", + "default": [], + "type": "array", + "items": { + "$ref": "#/definitions/ChatMessage" + } + }, + "manage_own_chat_context": { + "title": "Manage Own Chat Context", + "default": false, + "type": "boolean" + } + } + }, + "Observation": { + "title": "Observation", + "type": "object", + "properties": {} + }, + "HistoryNode": { + "title": "HistoryNode", + "description": "A point in history, a list of which make up History", + "type": "object", + "properties": { + "step": { + "$ref": "#/definitions/Step" + }, + "observation": { + "$ref": "#/definitions/Observation" + }, + "depth": { + "title": "Depth", + "type": "integer" + }, + "deleted": { + "title": "Deleted", + "default": false, + "type": "boolean" + }, + "active": { + "title": "Active", + "default": true, + "type": "boolean" + } + }, + "required": [ + "step", + "depth" + ] + }, + "History": { + "title": "History", + "description": "A history of steps taken and their results", + "type": "object", + "properties": { + "timeline": { + "title": "Timeline", + "type": "array", + "items": { + "$ref": "#/definitions/HistoryNode" + } + }, + "current_index": { + "title": "Current Index", + "type": "integer" + } + }, + "required": [ + "timeline", + "current_index" + ] + }, + "Position": { + "title": "Position", + "type": "object", + "properties": { + "line": { + "title": "Line", + "type": "integer" + }, + "character": { + "title": "Character", + "type": "integer" + } + }, + "required": [ + "line", + "character" + ] + }, + "Range": { + "title": "Range", + "description": "A range in a file. 0-indexed.", + "type": "object", + "properties": { + "start": { + "$ref": "#/definitions/Position" + }, + "end": { + "$ref": "#/definitions/Position" + } + }, + "required": [ + "start", + "end" + ] + }, + "RangeInFileWithContents": { + "title": "RangeInFileWithContents", + "description": "A range in a file with the contents of the range.", + "type": "object", + "properties": { + "filepath": { + "title": "Filepath", + "type": "string" + }, + "range": { + "$ref": "#/definitions/Range" + }, + "contents": { + "title": "Contents", + "type": "string" + } + }, + "required": [ + "filepath", + "range", + "contents" + ] + }, + "HighlightedRangeContext": { + "title": "HighlightedRangeContext", + "description": "Context for a highlighted range", + "type": "object", + "properties": { + "range": { + "$ref": "#/definitions/RangeInFileWithContents" + }, + "editing": { + "title": "Editing", + "type": "boolean" + }, + "pinned": { + "title": "Pinned", + "type": "boolean" + } + }, + "required": [ + "range", + "editing", + "pinned" + ] + }, + "SlashCommandDescription": { + "title": "SlashCommandDescription", + "type": "object", + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "description": { + "title": "Description", + "type": "string" + } + }, + "required": [ + "name", + "description" + ] + }, + "src__continuedev__core__main__FullState": { + "title": "FullState", + "description": "A full state of the program, including the history", + "type": "object", + "properties": { + "history": { + "$ref": "#/definitions/History" + }, + "active": { + "title": "Active", + "type": "boolean" + }, + "user_input_queue": { + "title": "User Input Queue", + "type": "array", + "items": { + "type": "string" + } + }, + "default_model": { + "title": "Default Model", + "type": "string" + }, + "highlighted_ranges": { + "title": "Highlighted Ranges", + "type": "array", + "items": { + "$ref": "#/definitions/HighlightedRangeContext" + } + }, + "slash_commands": { + "title": "Slash Commands", + "type": "array", + "items": { + "$ref": "#/definitions/SlashCommandDescription" + } + }, + "adding_highlighted_code": { + "title": "Adding Highlighted Code", + "type": "boolean" + } + }, + "required": [ + "history", + "active", + "user_input_queue", + "default_model", + "highlighted_ranges", + "slash_commands", + "adding_highlighted_code" + ] + } + } +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 9aa76f429b4f2a75bdd4696bb1f9737de00da410 Mon Sep 17 00:00:00 2001 From: Ty Dunn Date: Mon, 10 Jul 2023 15:44:35 -0700 Subject: update for v2 --- README.md | 22 ++++++++++----------- docs/docs/how-to-use-continue.md | 40 +++++++++++++++++++++++++++++++++++++++ edit.gif | Bin 11209423 -> 14939314 bytes extension/README.md | 18 +++++++++--------- extension/media/edit.png | Bin 246984 -> 675283 bytes extension/media/explain.png | Bin 464952 -> 897037 bytes extension/media/generate.png | Bin 1049613 -> 411580 bytes extension/package.json | 6 +++--- 8 files changed, 63 insertions(+), 23 deletions(-) (limited to 'extension/media') diff --git a/README.md b/README.md index a91fbdf4..01462247 100644 --- a/README.md +++ b/README.md @@ -19,26 +19,26 @@ ## Task, not tab, auto-complete -### Edit in natural language - ### Get possible explainations Ask Continue about a part of your code to get another perspective -- `what might cause this error?` -- `what is the load_dotenv library name?` -- `how do I find running process on port 8000?` +- “how can I set up a Prisma schema that cascades deletes?” +- “where in the page should I be making this request to the backend?” +- “how can I communicate between these iframes?” + +### Edit in natural language Highlight a section of code and instruct Continue to refactor it -- `/edit Make this use more descriptive variable names` -- `/edit Rewrite this API call to grab all pages` -- `/edit Use 'Union' instead of a vertical bar here` +- “/edit migrate this digital ocean terraform file into one that works for GCP” +- “/edit change this plot into a bar chart in this dashboard component” +- “/edit rewrite this function to be async” ### Generate files from scratch Let Continue build the scaffolding of Python scripts, React components, and more -- `Create a shell script to back up my home dir to /tmp/` -- `Write a Python script to get Posthog events` -- `Add a React component for syntax highlighted code` +- “/edit here is a connector for postgres, now write one for kafka” +- “/edit make an IAM policy that creates a user with read-only access to S3” +- “/edit use this schema to write me a SQL query that gets recently churned users” ## Getting Started diff --git a/docs/docs/how-to-use-continue.md b/docs/docs/how-to-use-continue.md index 96c44228..66de7ee9 100644 --- a/docs/docs/how-to-use-continue.md +++ b/docs/docs/how-to-use-continue.md @@ -29,42 +29,82 @@ Here are tasks that Continue excels at helping you complete: Continue works well in situations where find and replace does not work (i.e. “/edit change all of these to be like that”) +Examples +- "/edit Use 'Union' instead of a vertical bar here" +- “/edit Make this use more descriptive variable names” + ### Writing files from scratch Continue can help you get started building React components, Python scripts, Shell scripts, Makefiles, Unit tests, etc. +Examples +- “/edit write a python script to get Posthog events" +- “/edit add a React component for syntax highlighted code" + ### Creating projects from scratch Continue can go even further. For example, it can help build the scaffolding for a Python package, which includes a typer cli app to sort the arguments and print them back out. +Examples +- “/edit use this schema to write me a SQL query that gets recently churned users” +- “/edit create a shell script to back up my home dir to /tmp/" + ### Fix highlighted code After selecting a code section, try to refactor it with Continue (e.g “/edit change the function to work like this”, “/edit do this everywhere”) +Examples +- “/edit migrate this digital ocean terraform file into one that works for GCP” +- “/edit rewrite this function to be async” + ### Ask about highlighted code or an entire file If you don't understand how some code works, highlight it and ask "how does this code work?" +Examples +- “where in the page should I be making this request to the backend?” +- “how can I communicate between these iframes?” + ### Ask about errors Continue can also help explain errors and offer possible solutions. You will need to copy and paste the error text into the text input though. +Examples +- “explain this error to me in human understandable way” +- "what are some ideas for how I might solve this problem?" + ### Figure out what shell command to run Instead of switching windows and getting distracted, you can ask things like "How do I find running process on port 8000?" +Examples +- "what is the load_dotenv library name?" +- "how do I find running process on port 8000?" + ### Ask single-turn open-ended questions Instead of leaving your IDE, you can ask open-ended questions that you don't expect to turn into multi-turn conversations. +Examples +- “how can I set up a Prisma schema that cascades deletes?” +- "what is the difference between dense and sparse embeddings?" + ### Editing small existing files You can highlight an entire file and ask Continue to improve it as long as the file is not too large. +Examples +- “/edit here is a connector for postgres, now write one for kafka” +- "/edit Rewrite this API call to grab all pages" + ### Tasks with a few steps There are many more tasks that Continue can help you complete. Typically, these will be tasks that don't involve too many steps to complete. +Examples +- “/edit make an IAM policy that creates a user with read-only access to S3” +- “/edit change this plot into a bar chart in this dashboard component” + ## When to not use Continue Here are tasks that Continue is **not** helpful with today: diff --git a/edit.gif b/edit.gif index 6a53a14b..96240dfe 100644 Binary files a/edit.gif and b/edit.gif differ diff --git a/extension/README.md b/extension/README.md index b57aedb7..2d449b92 100644 --- a/extension/README.md +++ b/extension/README.md @@ -7,23 +7,23 @@ ### Get possible explainations Ask Continue about a part of your code to get another perspective -- `what might cause this error?` -- `what is the load_dotenv library name?` -- `how do I find running process on port 8000?` +- “how can I set up a Prisma schema that cascades deletes?” +- “where in the page should I be making this request to the backend?” +- “how can I communicate between these iframes?” ### Edit in natural language Highlight a section of code and instruct Continue to refactor it -- `/edit Make this use more descriptive variable names` -- `/edit Rewrite this API call to grab all pages` -- `/edit Use 'Union' instead of a vertical bar here` +- “/edit migrate this digital ocean terraform file into one that works for GCP” +- “/edit change this plot into a bar chart in this dashboard component” +- “/edit rewrite this function to be async” ### Generate files from scratch Let Continue build the scaffolding of Python scripts, React components, and more -- `Create a shell script to back up my home dir to /tmp/` -- `Write Python in a new file to get Posthog events` -- `Add a React component for syntax highlighted code` +- “/edit here is a connector for postgres, now write one for kafka” +- “/edit make an IAM policy that creates a user with read-only access to S3” +- “/edit use this schema to write me a SQL query that gets recently churned users” ## OpenAI API Key diff --git a/extension/media/edit.png b/extension/media/edit.png index 5e77c0ea..f4ca623c 100644 Binary files a/extension/media/edit.png and b/extension/media/edit.png differ diff --git a/extension/media/explain.png b/extension/media/explain.png index 196ab914..79e8ccc9 100644 Binary files a/extension/media/explain.png and b/extension/media/explain.png differ diff --git a/extension/media/generate.png b/extension/media/generate.png index 9d84e4ae..c16d9f9f 100644 Binary files a/extension/media/generate.png and b/extension/media/generate.png differ diff --git a/extension/package.json b/extension/package.json index 444372f8..0477a450 100644 --- a/extension/package.json +++ b/extension/package.json @@ -181,7 +181,7 @@ { "id": "edit", "title": "Edit in natural language", - "description": "Highlight a section of code and instruct Continue to refactor it (e.g. `/edit Make this use more descriptive variable names`)", + "description": "Highlight a section of code and instruct Continue to refactor it (e.g. `/edit rewrite this function to be async`)", "media": { "image": "media/edit.png", "altText": "Empty image" @@ -191,7 +191,7 @@ { "id": "explain", "title": "Get possible explanations", - "description": "Ask Continue about a part of your code to get another perspective (e.g. `how do I find running process on port 8000?`)", + "description": "Ask Continue about a part of your code to get another perspective (e.g. `where in the page should I be making this request to the backend?`)", "media": { "image": "media/explain.png", "altText": "Empty image" @@ -201,7 +201,7 @@ { "id": "generate", "title": "Generate files from scratch", - "description": "Let Continue build the scaffolding of Python scripts, React components, and more (e.g. `Create a shell script to back up my home dir to /tmp/`)", + "description": "Let Continue build the scaffolding of Python scripts, React components, and more (e.g. `/edit here is a connector for postgres, now write one for kafka`)", "media": { "image": "media/generate.png", "altText": "Empty image" -- cgit v1.2.3-70-g09d2 From 8c7ad065810a867c70d5a948bb54d94c44b6090a Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Mon, 24 Jul 2023 14:59:43 -0700 Subject: fixes from merge, images --- continuedev/src/continuedev/core/autopilot.py | 6 +- .../context_providers/file_context_provider.py | 54 ------ .../highlighted_code_context_provider.py | 191 --------------------- .../context_providers/file_context_provider.py | 55 ++++++ .../highlighted_code_context_provider.py | 191 +++++++++++++++++++++ .../continuedev/plugins/steps/custom_command.py | 2 +- extension/media/continue-dev-square.png | Bin 0 -> 36355 bytes extension/media/terminal-continue.png | Bin 0 -> 36669 bytes extension/package.json | 4 +- schema/json/ContextItem.json | 4 +- 10 files changed, 254 insertions(+), 253 deletions(-) delete mode 100644 continuedev/src/continuedev/libs/context_providers/file_context_provider.py delete mode 100644 continuedev/src/continuedev/libs/context_providers/highlighted_code_context_provider.py create mode 100644 continuedev/src/continuedev/plugins/context_providers/file_context_provider.py create mode 100644 continuedev/src/continuedev/plugins/context_providers/highlighted_code_context_provider.py create mode 100644 extension/media/continue-dev-square.png create mode 100644 extension/media/terminal-continue.png (limited to 'extension/media') diff --git a/continuedev/src/continuedev/core/autopilot.py b/continuedev/src/continuedev/core/autopilot.py index 003962c6..2ce7c1f9 100644 --- a/continuedev/src/continuedev/core/autopilot.py +++ b/continuedev/src/continuedev/core/autopilot.py @@ -10,12 +10,12 @@ from ..models.filesystem import RangeInFileWithContents from ..models.filesystem_edit import FileEditWithFullContents from .observation import Observation, InternalErrorObservation from .context import ContextManager -from ..libs.context_providers.file_context_provider import FileContextProvider -from ..libs.context_providers.highlighted_code_context_provider import HighlightedCodeContextProvider +from ..plugins.context_providers.file_context_provider import FileContextProvider +from ..plugins.context_providers.highlighted_code_context_provider import HighlightedCodeContextProvider from ..server.ide_protocol import AbstractIdeProtocolServer from ..libs.util.queue import AsyncSubscriptionQueue from ..models.main import ContinueBaseModel -from .main import Context, ContinueCustomException, HighlightedRangeContext, Policy, History, FullState, Step, HistoryNode +from .main import Context, ContinueCustomException, Policy, History, FullState, Step, HistoryNode from ..plugins.steps.core.core import ReversibleStep, ManualEditStep, UserInputStep from ..libs.util.telemetry import capture_event from .sdk import ContinueSDK diff --git a/continuedev/src/continuedev/libs/context_providers/file_context_provider.py b/continuedev/src/continuedev/libs/context_providers/file_context_provider.py deleted file mode 100644 index c3ec351f..00000000 --- a/continuedev/src/continuedev/libs/context_providers/file_context_provider.py +++ /dev/null @@ -1,54 +0,0 @@ -import os -from typing import List -from ...core.main import ContextItem, ContextItemDescription, ContextItemId -from ...core.context import ContextProvider -from fnmatch import fnmatch - - -def get_file_contents(filepath: str) -> str: - with open(filepath, "r") as f: - return f.read() - - -class FileContextProvider(ContextProvider): - """ - The FileContextProvider is a ContextProvider that allows you to search files in the open workspace. - """ - - title = "file" - workspace_dir: str - ignore_patterns: List[str] = list(map(lambda folder: f"**/{folder}", [ - ".git", - ".vscode", - ".idea", - ".vs", - ".venv", - "env", - ".env", - "node_modules", - "dist", - "build", - "target", - "out", - "bin", - ])) - - async def provide_context_items(self) -> List[ContextItem]: - filepaths = [] - for root, dir_names, file_names in os.walk(self.workspace_dir): - dir_names[:] = [d for d in dir_names if not any( - fnmatch(d, pattern) for pattern in self.ignore_patterns)] - for file_name in file_names: - filepaths.append(os.path.join(root, file_name)) - - return [ContextItem( - content=get_file_contents(file), - description=ContextItemDescription( - name=f"File {os.path.basename(file)}", - description=file, - id=ContextItemId( - provider_title=self.title, - item_id=file - ) - ) - ) for file in filepaths] diff --git a/continuedev/src/continuedev/libs/context_providers/highlighted_code_context_provider.py b/continuedev/src/continuedev/libs/context_providers/highlighted_code_context_provider.py deleted file mode 100644 index 23d4fc86..00000000 --- a/continuedev/src/continuedev/libs/context_providers/highlighted_code_context_provider.py +++ /dev/null @@ -1,191 +0,0 @@ -import os -from typing import Any, Dict, List - -import meilisearch -from ...core.main import ChatMessage -from ...models.filesystem import RangeInFile, RangeInFileWithContents -from ...core.context import ContextItem, ContextItemDescription, ContextItemId -from pydantic import BaseModel - - -class HighlightedRangeContextItem(BaseModel): - rif: RangeInFileWithContents - item: ContextItem - - -class HighlightedCodeContextProvider(BaseModel): - """ - The ContextProvider class is a plugin that lets you provide new information to the LLM by typing '@'. - When you type '@', the context provider will be asked to populate a list of options. - These options will be updated on each keystroke. - When you hit enter on an option, the context provider will add that item to the autopilot's list of context (which is all stored in the ContextManager object). - """ - - title = "code" - - ide: Any # IdeProtocolServer - - highlighted_ranges: List[HighlightedRangeContextItem] = [] - adding_highlighted_code: bool = False - - should_get_fallback_context_item: bool = True - last_added_fallback: bool = False - - async def _get_fallback_context_item(self) -> HighlightedRangeContextItem: - if not self.should_get_fallback_context_item: - return None - - visible_files = await self.ide.getVisibleFiles() - if len(visible_files) > 0: - content = await self.ide.readFile(visible_files[0]) - rif = RangeInFileWithContents.from_entire_file( - visible_files[0], content) - - item = self._rif_to_context_item(rif, 0, True) - item.description.name = self._rif_to_name( - rif, show_line_nums=False) - - self.last_added_fallback = True - return HighlightedRangeContextItem(rif=rif, item=item) - - return None - - async def get_selected_items(self) -> List[ContextItem]: - items = [hr.item for hr in self.highlighted_ranges] - - if len(items) == 0 and (fallback_item := await self._get_fallback_context_item()): - items = [fallback_item.item] - - return items - - async def get_chat_messages(self) -> List[ContextItem]: - ranges = self.highlighted_ranges - if len(ranges) == 0 and (fallback_item := await self._get_fallback_context_item()): - ranges = [fallback_item] - - return [ChatMessage( - role="user", - content=f"Code in this file is highlighted ({r.rif.filepath}):\n```\n{r.rif.contents}\n```", - summary=f"Code in this file is highlighted: {r.rif.filepath}" - ) for r in ranges] - - def _make_sure_is_editing_range(self): - """If none of the highlighted ranges are currently being edited, the first should be selected""" - if len(self.highlighted_ranges) == 0: - return - if not any(map(lambda x: x.item.editing, self.highlighted_ranges)): - self.highlighted_ranges[0].item.editing = True - - def _disambiguate_highlighted_ranges(self): - """If any files have the same name, also display their folder name""" - name_status: Dict[str, set] = { - } # basename -> set of full paths with that basename - for hr in self.highlighted_ranges: - basename = os.path.basename(hr.rif.filepath) - if basename in name_status: - name_status[basename].add(hr.rif.filepath) - else: - name_status[basename] = {hr.rif.filepath} - - for hr in self.highlighted_ranges: - if len(name_status[basename]) > 1: - hr.item.description.name = self._rif_to_name(hr.rif, display_filename=os.path.join( - os.path.basename(os.path.dirname(hr.rif.filepath)), basename)) - else: - hr.item.description.name = self._rif_to_name( - hr.rif, display_filename=basename) - - async def provide_context_items(self) -> List[ContextItem]: - return [] - - async def delete_context_with_ids(self, ids: List[ContextItemId]) -> List[ContextItem]: - indices_to_delete = [ - int(id.item_id) for id in ids - ] - - kept_ranges = [] - for i, hr in enumerate(self.highlighted_ranges): - if i not in indices_to_delete: - kept_ranges.append(hr) - self.highlighted_ranges = kept_ranges - - self._make_sure_is_editing_range() - - if len(self.highlighted_ranges) == 0 and self.last_added_fallback: - self.should_get_fallback_context_item = False - - return [hr.item for hr in self.highlighted_ranges] - - def _rif_to_name(self, rif: RangeInFileWithContents, display_filename: str = None, show_line_nums: bool = True) -> str: - line_nums = f" ({rif.range.start.line + 1}-{rif.range.end.line + 1})" if show_line_nums else "" - return f"{display_filename or os.path.basename(rif.filepath)}{line_nums}" - - def _rif_to_context_item(self, rif: RangeInFileWithContents, idx: int, editing: bool) -> ContextItem: - return ContextItem( - description=ContextItemDescription( - name=self._rif_to_name(rif), - description=rif.filepath, - id=ContextItemId( - provider_title=self.title, - item_id=str(idx) - ) - ), - content=rif.contents, - editing=editing, - editable=True - ) - - async def handle_highlighted_code(self, range_in_files: List[RangeInFileWithContents]): - self.should_get_fallback_context_item = True - self.last_added_fallback = False - - # Filter out rifs from ~/.continue/diffs folder - range_in_files = [ - rif for rif in range_in_files if not os.path.dirname(rif.filepath) == os.path.expanduser("~/.continue/diffs")] - - # If not adding highlighted code - if not self.adding_highlighted_code: - if len(self.highlighted_ranges) == 1 and len(range_in_files) <= 1 and (len(range_in_files) == 0 or range_in_files[0].range.start == range_in_files[0].range.end): - # If un-highlighting the range to edit, then remove the range - self.highlighted_ranges = [] - elif len(range_in_files) > 0: - # Otherwise, replace the current range with the new one - # This is the first range to be highlighted - self.highlighted_ranges = [ - HighlightedRangeContextItem( - rif=range_in_files[0], - item=self._rif_to_context_item(range_in_files[0], 0, True))] - - return - - # If current range overlaps with any others, delete them and only keep the new range - new_ranges = [] - for i, hr in enumerate(self.highlighted_ranges): - found_overlap = False - for new_rif in range_in_files: - if hr.rif.filepath == new_rif.filepath and hr.rif.range.overlaps_with(new_rif.range): - found_overlap = True - break - - # Also don't allow multiple ranges in same file with same content. This is useless to the model, and avoids - # the bug where cmd+f causes repeated highlights - if hr.rif.filepath == new_rif.filepath and hr.rif.contents == new_rif.contents: - found_overlap = True - break - - if not found_overlap: - new_ranges.append(HighlightedRangeContextItem(rif=hr.rif, item=self._rif_to_context_item( - hr.rif, len(new_ranges), False))) - - self.highlighted_ranges = new_ranges + [HighlightedRangeContextItem(rif=rif, item=self._rif_to_context_item( - rif, len(new_ranges) + idx, False)) for idx, rif in enumerate(range_in_files)] - - self._make_sure_is_editing_range() - self._disambiguate_highlighted_ranges() - - async def set_editing_at_ids(self, ids: List[str]): - for hr in self.highlighted_ranges: - hr.item.editing = hr.item.description.id.to_string() in ids - - async def add_context_item(self, id: ContextItemId, query: str, search_client: meilisearch.Client, prev: List[ContextItem] = None) -> List[ContextItem]: - raise NotImplementedError() diff --git a/continuedev/src/continuedev/plugins/context_providers/file_context_provider.py b/continuedev/src/continuedev/plugins/context_providers/file_context_provider.py new file mode 100644 index 00000000..854310b1 --- /dev/null +++ b/continuedev/src/continuedev/plugins/context_providers/file_context_provider.py @@ -0,0 +1,55 @@ +import os +from typing import List +from ...core.main import ContextItem, ContextItemDescription, ContextItemId +from ...core.context import ContextProvider +from fnmatch import fnmatch + + +def get_file_contents(filepath: str) -> str: + with open(filepath, "r") as f: + return f.read() + + +class FileContextProvider(ContextProvider): + """ + The FileContextProvider is a ContextProvider that allows you to search files in the open workspace. + """ + + title = "file" + workspace_dir: str + ignore_patterns: List[str] = list(map(lambda folder: f"**/{folder}", [ + ".git", + ".vscode", + ".idea", + ".vs", + ".venv", + "env", + ".env", + "node_modules", + "dist", + "build", + "target", + "out", + "bin", + ])) + + async def provide_context_items(self) -> List[ContextItem]: + filepaths = [] + for root, dir_names, file_names in os.walk(self.workspace_dir): + dir_names[:] = [d for d in dir_names if not any( + fnmatch(d, pattern) for pattern in self.ignore_patterns)] + for file_name in file_names: + filepaths.append(os.path.join(root, file_name)) + + return [ContextItem( + content=get_file_contents(file)[:min( + 2000, len(get_file_contents(file)))], + description=ContextItemDescription( + name=f"File {os.path.basename(file)}", + description=file, + id=ContextItemId( + provider_title=self.title, + item_id=file + ) + ) + ) for file in filepaths] diff --git a/continuedev/src/continuedev/plugins/context_providers/highlighted_code_context_provider.py b/continuedev/src/continuedev/plugins/context_providers/highlighted_code_context_provider.py new file mode 100644 index 00000000..23d4fc86 --- /dev/null +++ b/continuedev/src/continuedev/plugins/context_providers/highlighted_code_context_provider.py @@ -0,0 +1,191 @@ +import os +from typing import Any, Dict, List + +import meilisearch +from ...core.main import ChatMessage +from ...models.filesystem import RangeInFile, RangeInFileWithContents +from ...core.context import ContextItem, ContextItemDescription, ContextItemId +from pydantic import BaseModel + + +class HighlightedRangeContextItem(BaseModel): + rif: RangeInFileWithContents + item: ContextItem + + +class HighlightedCodeContextProvider(BaseModel): + """ + The ContextProvider class is a plugin that lets you provide new information to the LLM by typing '@'. + When you type '@', the context provider will be asked to populate a list of options. + These options will be updated on each keystroke. + When you hit enter on an option, the context provider will add that item to the autopilot's list of context (which is all stored in the ContextManager object). + """ + + title = "code" + + ide: Any # IdeProtocolServer + + highlighted_ranges: List[HighlightedRangeContextItem] = [] + adding_highlighted_code: bool = False + + should_get_fallback_context_item: bool = True + last_added_fallback: bool = False + + async def _get_fallback_context_item(self) -> HighlightedRangeContextItem: + if not self.should_get_fallback_context_item: + return None + + visible_files = await self.ide.getVisibleFiles() + if len(visible_files) > 0: + content = await self.ide.readFile(visible_files[0]) + rif = RangeInFileWithContents.from_entire_file( + visible_files[0], content) + + item = self._rif_to_context_item(rif, 0, True) + item.description.name = self._rif_to_name( + rif, show_line_nums=False) + + self.last_added_fallback = True + return HighlightedRangeContextItem(rif=rif, item=item) + + return None + + async def get_selected_items(self) -> List[ContextItem]: + items = [hr.item for hr in self.highlighted_ranges] + + if len(items) == 0 and (fallback_item := await self._get_fallback_context_item()): + items = [fallback_item.item] + + return items + + async def get_chat_messages(self) -> List[ContextItem]: + ranges = self.highlighted_ranges + if len(ranges) == 0 and (fallback_item := await self._get_fallback_context_item()): + ranges = [fallback_item] + + return [ChatMessage( + role="user", + content=f"Code in this file is highlighted ({r.rif.filepath}):\n```\n{r.rif.contents}\n```", + summary=f"Code in this file is highlighted: {r.rif.filepath}" + ) for r in ranges] + + def _make_sure_is_editing_range(self): + """If none of the highlighted ranges are currently being edited, the first should be selected""" + if len(self.highlighted_ranges) == 0: + return + if not any(map(lambda x: x.item.editing, self.highlighted_ranges)): + self.highlighted_ranges[0].item.editing = True + + def _disambiguate_highlighted_ranges(self): + """If any files have the same name, also display their folder name""" + name_status: Dict[str, set] = { + } # basename -> set of full paths with that basename + for hr in self.highlighted_ranges: + basename = os.path.basename(hr.rif.filepath) + if basename in name_status: + name_status[basename].add(hr.rif.filepath) + else: + name_status[basename] = {hr.rif.filepath} + + for hr in self.highlighted_ranges: + if len(name_status[basename]) > 1: + hr.item.description.name = self._rif_to_name(hr.rif, display_filename=os.path.join( + os.path.basename(os.path.dirname(hr.rif.filepath)), basename)) + else: + hr.item.description.name = self._rif_to_name( + hr.rif, display_filename=basename) + + async def provide_context_items(self) -> List[ContextItem]: + return [] + + async def delete_context_with_ids(self, ids: List[ContextItemId]) -> List[ContextItem]: + indices_to_delete = [ + int(id.item_id) for id in ids + ] + + kept_ranges = [] + for i, hr in enumerate(self.highlighted_ranges): + if i not in indices_to_delete: + kept_ranges.append(hr) + self.highlighted_ranges = kept_ranges + + self._make_sure_is_editing_range() + + if len(self.highlighted_ranges) == 0 and self.last_added_fallback: + self.should_get_fallback_context_item = False + + return [hr.item for hr in self.highlighted_ranges] + + def _rif_to_name(self, rif: RangeInFileWithContents, display_filename: str = None, show_line_nums: bool = True) -> str: + line_nums = f" ({rif.range.start.line + 1}-{rif.range.end.line + 1})" if show_line_nums else "" + return f"{display_filename or os.path.basename(rif.filepath)}{line_nums}" + + def _rif_to_context_item(self, rif: RangeInFileWithContents, idx: int, editing: bool) -> ContextItem: + return ContextItem( + description=ContextItemDescription( + name=self._rif_to_name(rif), + description=rif.filepath, + id=ContextItemId( + provider_title=self.title, + item_id=str(idx) + ) + ), + content=rif.contents, + editing=editing, + editable=True + ) + + async def handle_highlighted_code(self, range_in_files: List[RangeInFileWithContents]): + self.should_get_fallback_context_item = True + self.last_added_fallback = False + + # Filter out rifs from ~/.continue/diffs folder + range_in_files = [ + rif for rif in range_in_files if not os.path.dirname(rif.filepath) == os.path.expanduser("~/.continue/diffs")] + + # If not adding highlighted code + if not self.adding_highlighted_code: + if len(self.highlighted_ranges) == 1 and len(range_in_files) <= 1 and (len(range_in_files) == 0 or range_in_files[0].range.start == range_in_files[0].range.end): + # If un-highlighting the range to edit, then remove the range + self.highlighted_ranges = [] + elif len(range_in_files) > 0: + # Otherwise, replace the current range with the new one + # This is the first range to be highlighted + self.highlighted_ranges = [ + HighlightedRangeContextItem( + rif=range_in_files[0], + item=self._rif_to_context_item(range_in_files[0], 0, True))] + + return + + # If current range overlaps with any others, delete them and only keep the new range + new_ranges = [] + for i, hr in enumerate(self.highlighted_ranges): + found_overlap = False + for new_rif in range_in_files: + if hr.rif.filepath == new_rif.filepath and hr.rif.range.overlaps_with(new_rif.range): + found_overlap = True + break + + # Also don't allow multiple ranges in same file with same content. This is useless to the model, and avoids + # the bug where cmd+f causes repeated highlights + if hr.rif.filepath == new_rif.filepath and hr.rif.contents == new_rif.contents: + found_overlap = True + break + + if not found_overlap: + new_ranges.append(HighlightedRangeContextItem(rif=hr.rif, item=self._rif_to_context_item( + hr.rif, len(new_ranges), False))) + + self.highlighted_ranges = new_ranges + [HighlightedRangeContextItem(rif=rif, item=self._rif_to_context_item( + rif, len(new_ranges) + idx, False)) for idx, rif in enumerate(range_in_files)] + + self._make_sure_is_editing_range() + self._disambiguate_highlighted_ranges() + + async def set_editing_at_ids(self, ids: List[str]): + for hr in self.highlighted_ranges: + hr.item.editing = hr.item.description.id.to_string() in ids + + async def add_context_item(self, id: ContextItemId, query: str, search_client: meilisearch.Client, prev: List[ContextItem] = None) -> List[ContextItem]: + raise NotImplementedError() diff --git a/continuedev/src/continuedev/plugins/steps/custom_command.py b/continuedev/src/continuedev/plugins/steps/custom_command.py index 1491a975..419b3c3d 100644 --- a/continuedev/src/continuedev/plugins/steps/custom_command.py +++ b/continuedev/src/continuedev/plugins/steps/custom_command.py @@ -1,6 +1,6 @@ from ...libs.util.templating import render_templated_string from ...core.main import Step -from ...core.sdk import ContinueSDK +from ...core.sdk import ContinueSDK, Models from ..steps.chat import SimpleChatStep diff --git a/extension/media/continue-dev-square.png b/extension/media/continue-dev-square.png new file mode 100644 index 00000000..e4b62556 Binary files /dev/null and b/extension/media/continue-dev-square.png differ diff --git a/extension/media/terminal-continue.png b/extension/media/terminal-continue.png new file mode 100644 index 00000000..ef310fa3 Binary files /dev/null and b/extension/media/terminal-continue.png differ diff --git a/extension/package.json b/extension/package.json index 6618ff45..cfce77df 100644 --- a/extension/package.json +++ b/extension/package.json @@ -1,6 +1,6 @@ { "name": "continue", - "icon": "media/continue-gradient.png", + "icon": "media/terminal-continue.png", "repository": { "type": "git", "url": "https://github.com/continuedev/continue" @@ -157,7 +157,7 @@ { "id": "continue", "title": "Continue ", - "icon": "react-app/dist/play_button.png" + "icon": "media/continue-dev-square.png" } ] }, diff --git a/schema/json/ContextItem.json b/schema/json/ContextItem.json index 35766f11..32a214d3 100644 --- a/schema/json/ContextItem.json +++ b/schema/json/ContextItem.json @@ -1,6 +1,6 @@ { "title": "ContextItem", - "$ref": "#/definitions/src__continuedev__core__context__ContextItem", + "$ref": "#/definitions/src__continuedev__core__main__ContextItem", "definitions": { "ContextItemId": { "title": "ContextItemId", @@ -44,7 +44,7 @@ "id" ] }, - "src__continuedev__core__context__ContextItem": { + "src__continuedev__core__main__ContextItem": { "title": "ContextItem", "description": "A ContextItem is a single item that is stored in the ContextManager.", "type": "object", -- cgit v1.2.3-70-g09d2 From e6e9655caf982f68d22ceab857cfe692baad922f Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Mon, 24 Jul 2023 19:47:59 -0700 Subject: press start 2p font --- .../media/Lexend/Lexend-VariableFont_wght.ttf | Bin 176220 -> 0 bytes extension/media/Lexend/OFL.txt | 93 --------------------- extension/media/Lexend/README.txt | 71 ---------------- extension/media/Lexend/static/Lexend-Black.ttf | Bin 78496 -> 0 bytes extension/media/Lexend/static/Lexend-Bold.ttf | Bin 78632 -> 0 bytes extension/media/Lexend/static/Lexend-ExtraBold.ttf | Bin 78716 -> 0 bytes .../media/Lexend/static/Lexend-ExtraLight.ttf | Bin 78508 -> 0 bytes extension/media/Lexend/static/Lexend-Light.ttf | Bin 78668 -> 0 bytes extension/media/Lexend/static/Lexend-Medium.ttf | Bin 78696 -> 0 bytes extension/media/Lexend/static/Lexend-Regular.ttf | Bin 78360 -> 0 bytes extension/media/Lexend/static/Lexend-SemiBold.ttf | Bin 78744 -> 0 bytes extension/media/Lexend/static/Lexend-Thin.ttf | Bin 78380 -> 0 bytes .../react-app/src/components/ContinueButton.tsx | 4 +- extension/react-app/src/index.css | 4 + extension/react-app/src/pages/gui.tsx | 4 +- extension/src/debugPanel.ts | 1 + 16 files changed, 9 insertions(+), 168 deletions(-) delete mode 100644 extension/media/Lexend/Lexend-VariableFont_wght.ttf delete mode 100644 extension/media/Lexend/OFL.txt delete mode 100644 extension/media/Lexend/README.txt delete mode 100644 extension/media/Lexend/static/Lexend-Black.ttf delete mode 100644 extension/media/Lexend/static/Lexend-Bold.ttf delete mode 100644 extension/media/Lexend/static/Lexend-ExtraBold.ttf delete mode 100644 extension/media/Lexend/static/Lexend-ExtraLight.ttf delete mode 100644 extension/media/Lexend/static/Lexend-Light.ttf delete mode 100644 extension/media/Lexend/static/Lexend-Medium.ttf delete mode 100644 extension/media/Lexend/static/Lexend-Regular.ttf delete mode 100644 extension/media/Lexend/static/Lexend-SemiBold.ttf delete mode 100644 extension/media/Lexend/static/Lexend-Thin.ttf (limited to 'extension/media') diff --git a/extension/media/Lexend/Lexend-VariableFont_wght.ttf b/extension/media/Lexend/Lexend-VariableFont_wght.ttf deleted file mode 100644 index b294dc84..00000000 Binary files a/extension/media/Lexend/Lexend-VariableFont_wght.ttf and /dev/null differ diff --git a/extension/media/Lexend/OFL.txt b/extension/media/Lexend/OFL.txt deleted file mode 100644 index 6b679248..00000000 --- a/extension/media/Lexend/OFL.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2018 The Lexend Project Authors (https://github.com/googlefonts/lexend), with Reserved Font Name “RevReading Lexend”. - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/extension/media/Lexend/README.txt b/extension/media/Lexend/README.txt deleted file mode 100644 index f2966dfe..00000000 --- a/extension/media/Lexend/README.txt +++ /dev/null @@ -1,71 +0,0 @@ -Lexend Variable Font -==================== - -This download contains Lexend as both a variable font and static fonts. - -Lexend is a variable font with this axis: - wght - -This means all the styles are contained in a single file: - Lexend-VariableFont_wght.ttf - -If your app fully supports variable fonts, you can now pick intermediate styles -that aren’t available as static fonts. Not all apps support variable fonts, and -in those cases you can use the static font files for Lexend: - static/Lexend-Thin.ttf - static/Lexend-ExtraLight.ttf - static/Lexend-Light.ttf - static/Lexend-Regular.ttf - static/Lexend-Medium.ttf - static/Lexend-SemiBold.ttf - static/Lexend-Bold.ttf - static/Lexend-ExtraBold.ttf - static/Lexend-Black.ttf - -Get started ------------ - -1. Install the font files you want to use - -2. Use your app's font picker to view the font family and all the -available styles - -Learn more about variable fonts -------------------------------- - - https://developers.google.com/web/fundamentals/design-and-ux/typography/variable-fonts - https://variablefonts.typenetwork.com - https://medium.com/variable-fonts - -In desktop apps - - https://theblog.adobe.com/can-variable-fonts-illustrator-cc - https://helpx.adobe.com/nz/photoshop/using/fonts.html#variable_fonts - -Online - - https://developers.google.com/fonts/docs/getting_started - https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide - https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/variable-fonts - -Installing fonts - - MacOS: https://support.apple.com/en-us/HT201749 - Linux: https://www.google.com/search?q=how+to+install+a+font+on+gnu%2Blinux - Windows: https://support.microsoft.com/en-us/help/314960/how-to-install-or-remove-a-font-in-windows - -Android Apps - - https://developers.google.com/fonts/docs/android - https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts - -License -------- -Please read the full license text (OFL.txt) to understand the permissions, -restrictions and requirements for usage, redistribution, and modification. - -You can use them in your products & projects – print or digital, -commercial or otherwise. - -This isn't legal advice, please consider consulting a lawyer and see the full -license for all details. diff --git a/extension/media/Lexend/static/Lexend-Black.ttf b/extension/media/Lexend/static/Lexend-Black.ttf deleted file mode 100644 index 2fea087c..00000000 Binary files a/extension/media/Lexend/static/Lexend-Black.ttf and /dev/null differ diff --git a/extension/media/Lexend/static/Lexend-Bold.ttf b/extension/media/Lexend/static/Lexend-Bold.ttf deleted file mode 100644 index 95884f6e..00000000 Binary files a/extension/media/Lexend/static/Lexend-Bold.ttf and /dev/null differ diff --git a/extension/media/Lexend/static/Lexend-ExtraBold.ttf b/extension/media/Lexend/static/Lexend-ExtraBold.ttf deleted file mode 100644 index 02f84ed3..00000000 Binary files a/extension/media/Lexend/static/Lexend-ExtraBold.ttf and /dev/null differ diff --git a/extension/media/Lexend/static/Lexend-ExtraLight.ttf b/extension/media/Lexend/static/Lexend-ExtraLight.ttf deleted file mode 100644 index 20e7068d..00000000 Binary files a/extension/media/Lexend/static/Lexend-ExtraLight.ttf and /dev/null differ diff --git a/extension/media/Lexend/static/Lexend-Light.ttf b/extension/media/Lexend/static/Lexend-Light.ttf deleted file mode 100644 index fb6d097c..00000000 Binary files a/extension/media/Lexend/static/Lexend-Light.ttf and /dev/null differ diff --git a/extension/media/Lexend/static/Lexend-Medium.ttf b/extension/media/Lexend/static/Lexend-Medium.ttf deleted file mode 100644 index d91a8673..00000000 Binary files a/extension/media/Lexend/static/Lexend-Medium.ttf and /dev/null differ diff --git a/extension/media/Lexend/static/Lexend-Regular.ttf b/extension/media/Lexend/static/Lexend-Regular.ttf deleted file mode 100644 index b423d3ab..00000000 Binary files a/extension/media/Lexend/static/Lexend-Regular.ttf and /dev/null differ diff --git a/extension/media/Lexend/static/Lexend-SemiBold.ttf b/extension/media/Lexend/static/Lexend-SemiBold.ttf deleted file mode 100644 index 9dcb8214..00000000 Binary files a/extension/media/Lexend/static/Lexend-SemiBold.ttf and /dev/null differ diff --git a/extension/media/Lexend/static/Lexend-Thin.ttf b/extension/media/Lexend/static/Lexend-Thin.ttf deleted file mode 100644 index 0d7df881..00000000 Binary files a/extension/media/Lexend/static/Lexend-Thin.ttf and /dev/null differ diff --git a/extension/react-app/src/components/ContinueButton.tsx b/extension/react-app/src/components/ContinueButton.tsx index d7739b20..eda9bcff 100644 --- a/extension/react-app/src/components/ContinueButton.tsx +++ b/extension/react-app/src/components/ContinueButton.tsx @@ -26,7 +26,7 @@ function ContinueButton(props: { onClick?: () => void; hidden?: boolean }) { return ( ); } diff --git a/extension/react-app/src/index.css b/extension/react-app/src/index.css index bac7fe97..68f9d0ab 100644 --- a/extension/react-app/src/index.css +++ b/extension/react-app/src/index.css @@ -25,3 +25,7 @@ body { margin: 0px; height: 100%; } + +.press-start-2p { + font-family: "Press Start 2P", "Lexend", sans-serif; +} diff --git a/extension/react-app/src/pages/gui.tsx b/extension/react-app/src/pages/gui.tsx index 03b24349..d7efc288 100644 --- a/extension/react-app/src/pages/gui.tsx +++ b/extension/react-app/src/pages/gui.tsx @@ -415,7 +415,7 @@ function GUI(props: GUIProps) { {bottomMessage}