summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md22
-rw-r--r--continuedev/src/continuedev/core/autopilot.py4
-rw-r--r--continuedev/src/continuedev/libs/util/create_async_task.py23
-rw-r--r--continuedev/src/continuedev/server/gui.py55
-rw-r--r--continuedev/src/continuedev/server/ide.py21
-rw-r--r--continuedev/src/continuedev/server/session_manager.py9
-rw-r--r--continuedev/src/continuedev/steps/search_directory.py5
-rw-r--r--docs/docs/how-to-use-continue.md40
-rw-r--r--edit.gifbin11209423 -> 14939314 bytes
-rw-r--r--extension/README.md18
-rw-r--r--extension/media/edit.pngbin246984 -> 675283 bytes
-rw-r--r--extension/media/explain.pngbin464952 -> 897037 bytes
-rw-r--r--extension/media/generate.pngbin1049613 -> 411580 bytes
-rw-r--r--extension/package-lock.json4
-rw-r--r--extension/package.json8
-rw-r--r--extension/react-app/src/components/Onboarding.tsx115
-rw-r--r--extension/react-app/src/tabs/gui.tsx2
-rw-r--r--extension/src/continueIdeClient.ts2
-rw-r--r--media/edit.gifbin0 -> 41667733 bytes
-rw-r--r--media/explain.gifbin0 -> 56475028 bytes
-rw-r--r--media/generate.gifbin0 -> 32532380 bytes
-rw-r--r--media/intro.gifbin0 -> 3976676 bytes
22 files changed, 262 insertions, 66 deletions
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/continuedev/src/continuedev/core/autopilot.py b/continuedev/src/continuedev/core/autopilot.py
index 5c3baafd..615e7657 100644
--- a/continuedev/src/continuedev/core/autopilot.py
+++ b/continuedev/src/continuedev/core/autopilot.py
@@ -20,6 +20,7 @@ import asyncio
from ..libs.util.step_name_to_steps import get_step_from_name
from ..libs.util.traceback_parsers import get_python_traceback, get_javascript_traceback
from openai import error as openai_errors
+from ..libs.util.create_async_task import create_async_task
def get_error_title(e: Exception) -> str:
@@ -341,7 +342,8 @@ class Autopilot(ContinueBaseModel):
# Update subscribers with new description
await self.update_subscribers()
- asyncio.create_task(update_description())
+ create_async_task(update_description(),
+ self.continue_sdk.ide.unique_id)
return observation
diff --git a/continuedev/src/continuedev/libs/util/create_async_task.py b/continuedev/src/continuedev/libs/util/create_async_task.py
new file mode 100644
index 00000000..608d4977
--- /dev/null
+++ b/continuedev/src/continuedev/libs/util/create_async_task.py
@@ -0,0 +1,23 @@
+from typing import Coroutine, Union
+import traceback
+from .telemetry import capture_event
+import asyncio
+import nest_asyncio
+nest_asyncio.apply()
+
+
+def create_async_task(coro: Coroutine, unique_id: Union[str, None] = None):
+ """asyncio.create_task and log errors by adding a callback"""
+ task = asyncio.create_task(coro)
+
+ def callback(future: asyncio.Future):
+ try:
+ future.result()
+ except Exception as e:
+ print("Exception caught from async task: ", e)
+ capture_event(unique_id or "None", "async_task_error", {
+ "error_title": e.__str__() or e.__repr__(), "error_message": traceback.format_tb(e.__traceback__)
+ })
+
+ task.add_done_callback(callback)
+ return task
diff --git a/continuedev/src/continuedev/server/gui.py b/continuedev/src/continuedev/server/gui.py
index 8e9b1fb9..ae53be00 100644
--- a/continuedev/src/continuedev/server/gui.py
+++ b/continuedev/src/continuedev/server/gui.py
@@ -2,14 +2,14 @@ import json
from fastapi import Depends, Header, WebSocket, APIRouter
from typing import Any, List, Type, TypeVar, Union
from pydantic import BaseModel
+import traceback
from uvicorn.main import Server
from .session_manager import SessionManager, session_manager, Session
from .gui_protocol import AbstractGUIProtocolServer
from ..libs.util.queue import AsyncSubscriptionQueue
-import asyncio
-import nest_asyncio
-nest_asyncio.apply()
+from ..libs.util.telemetry import capture_event
+from ..libs.util.create_async_task import create_async_task
router = APIRouter(prefix="/gui", tags=["gui"])
@@ -102,51 +102,60 @@ class GUIProtocolServer(AbstractGUIProtocolServer):
def on_main_input(self, input: str):
# Do something with user input
- asyncio.create_task(self.session.autopilot.accept_user_input(input))
+ create_async_task(self.session.autopilot.accept_user_input(
+ input), self.session.autopilot.continue_sdk.ide.unique_id)
def on_reverse_to_index(self, index: int):
# Reverse the history to the given index
- asyncio.create_task(self.session.autopilot.reverse_to_index(index))
+ create_async_task(self.session.autopilot.reverse_to_index(
+ index), self.session.autopilot.continue_sdk.ide.unique_id)
def on_step_user_input(self, input: str, index: int):
- asyncio.create_task(
- self.session.autopilot.give_user_input(input, index))
+ create_async_task(
+ self.session.autopilot.give_user_input(input, index), self.session.autopilot.continue_sdk.ide.unique_id)
def on_refinement_input(self, input: str, index: int):
- asyncio.create_task(
- self.session.autopilot.accept_refinement_input(input, index))
+ create_async_task(
+ self.session.autopilot.accept_refinement_input(input, index), self.session.autopilot.continue_sdk.ide.unique_id)
def on_retry_at_index(self, index: int):
- asyncio.create_task(
- self.session.autopilot.retry_at_index(index))
+ create_async_task(
+ self.session.autopilot.retry_at_index(index), self.session.autopilot.continue_sdk.ide.unique_id)
def on_change_default_model(self, model: str):
- asyncio.create_task(self.session.autopilot.change_default_model(model))
+ create_async_task(self.session.autopilot.change_default_model(
+ model), self.session.autopilot.continue_sdk.ide.unique_id)
def on_clear_history(self):
- asyncio.create_task(self.session.autopilot.clear_history())
+ create_async_task(self.session.autopilot.clear_history(
+ ), self.session.autopilot.continue_sdk.ide.unique_id)
def on_delete_at_index(self, index: int):
- asyncio.create_task(self.session.autopilot.delete_at_index(index))
+ create_async_task(self.session.autopilot.delete_at_index(
+ index), self.session.autopilot.continue_sdk.ide.unique_id)
def on_delete_context_at_indices(self, indices: List[int]):
- asyncio.create_task(
- self.session.autopilot.delete_context_at_indices(indices)
+ create_async_task(
+ self.session.autopilot.delete_context_at_indices(
+ indices), self.session.autopilot.continue_sdk.ide.unique_id
)
def on_toggle_adding_highlighted_code(self):
- asyncio.create_task(
- self.session.autopilot.toggle_adding_highlighted_code()
+ create_async_task(
+ self.session.autopilot.toggle_adding_highlighted_code(
+ ), self.session.autopilot.continue_sdk.ide.unique_id
)
def on_set_editing_at_indices(self, indices: List[int]):
- asyncio.create_task(
- self.session.autopilot.set_editing_at_indices(indices)
+ create_async_task(
+ self.session.autopilot.set_editing_at_indices(
+ indices), self.session.autopilot.continue_sdk.ide.unique_id
)
def on_set_pinned_at_indices(self, indices: List[int]):
- asyncio.create_task(
- self.session.autopilot.set_pinned_at_indices(indices)
+ create_async_task(
+ self.session.autopilot.set_pinned_at_indices(
+ indices), self.session.autopilot.continue_sdk.ide.unique_id
)
@@ -179,6 +188,8 @@ async def websocket_endpoint(websocket: WebSocket, session: Session = Depends(we
except Exception as e:
print("ERROR in gui websocket: ", e)
+ capture_event(session.autopilot.continue_sdk.ide.unique_id, "gui_error", {
+ "error_title": e.__str__() or e.__repr__(), "error_message": traceback.format_tb(e.__traceback__)})
raise e
finally:
print("Closing gui websocket")
diff --git a/continuedev/src/continuedev/server/ide.py b/continuedev/src/continuedev/server/ide.py
index e4a6266a..93996edd 100644
--- a/continuedev/src/continuedev/server/ide.py
+++ b/continuedev/src/continuedev/server/ide.py
@@ -6,6 +6,7 @@ from typing import Any, Dict, List, Type, TypeVar, Union
import uuid
from fastapi import WebSocket, Body, APIRouter
from uvicorn.main import Server
+import traceback
from ..libs.util.telemetry import capture_event
from ..libs.util.queue import AsyncSubscriptionQueue
@@ -15,8 +16,7 @@ from pydantic import BaseModel
from .gui import SessionManager, session_manager
from .ide_protocol import AbstractIdeProtocolServer
import asyncio
-import nest_asyncio
-nest_asyncio.apply()
+from ..libs.util.create_async_task import create_async_task
router = APIRouter(prefix="/ide", tags=["ide"])
@@ -250,24 +250,25 @@ class IdeProtocolServer(AbstractIdeProtocolServer):
def onDeleteAtIndex(self, index: int):
for _, session in self.session_manager.sessions.items():
- asyncio.create_task(session.autopilot.delete_at_index(index))
+ create_async_task(
+ session.autopilot.delete_at_index(index), self.unique_id)
def onCommandOutput(self, output: str):
# Send the output to ALL autopilots.
# Maybe not ideal behavior
for _, session in self.session_manager.sessions.items():
- asyncio.create_task(
- session.autopilot.handle_command_output(output))
+ create_async_task(
+ session.autopilot.handle_command_output(output), self.unique_id)
def onHighlightedCodeUpdate(self, range_in_files: List[RangeInFileWithContents]):
for _, session in self.session_manager.sessions.items():
- asyncio.create_task(
- session.autopilot.handle_highlighted_code(range_in_files))
+ create_async_task(
+ session.autopilot.handle_highlighted_code(range_in_files), self.unique_id)
def onMainUserInput(self, input: str):
for _, session in self.session_manager.sessions.items():
- asyncio.create_task(
- session.autopilot.accept_user_input(input))
+ create_async_task(
+ session.autopilot.accept_user_input(input), self.unique_id)
# Request information. Session doesn't matter.
async def getOpenFiles(self) -> List[str]:
@@ -412,5 +413,7 @@ async def websocket_endpoint(websocket: WebSocket):
await websocket.close()
except Exception as e:
print("Error in ide websocket: ", e)
+ capture_event(ideProtocolServer.unique_id, "gui_error", {
+ "error_title": e.__str__() or e.__repr__(), "error_message": traceback.format_tb(e.__traceback__)})
await websocket.close()
raise e
diff --git a/continuedev/src/continuedev/server/session_manager.py b/continuedev/src/continuedev/server/session_manager.py
index 99a38146..873a379e 100644
--- a/continuedev/src/continuedev/server/session_manager.py
+++ b/continuedev/src/continuedev/server/session_manager.py
@@ -1,3 +1,4 @@
+from asyncio import BaseEventLoop
from fastapi import WebSocket
from typing import Any, Dict, List, Union
from uuid import uuid4
@@ -7,9 +8,7 @@ from ..core.policy import DemoPolicy
from ..core.main import FullState
from ..core.autopilot import Autopilot
from .ide_protocol import AbstractIdeProtocolServer
-import asyncio
-import nest_asyncio
-nest_asyncio.apply()
+from ..libs.util.create_async_task import create_async_task
class Session:
@@ -38,7 +37,7 @@ class DemoAutopilot(Autopilot):
class SessionManager:
sessions: Dict[str, Session] = {}
- _event_loop: Union[asyncio.BaseEventLoop, None] = None
+ _event_loop: Union[BaseEventLoop, None] = None
def get_session(self, session_id: str) -> Session:
if session_id not in self.sessions:
@@ -57,7 +56,7 @@ class SessionManager:
})
autopilot.on_update(on_update)
- asyncio.create_task(autopilot.run_policy())
+ create_async_task(autopilot.run_policy())
return session_id
def remove_session(self, session_id: str):
diff --git a/continuedev/src/continuedev/steps/search_directory.py b/continuedev/src/continuedev/steps/search_directory.py
index 2eecc99c..bfb97630 100644
--- a/continuedev/src/continuedev/steps/search_directory.py
+++ b/continuedev/src/continuedev/steps/search_directory.py
@@ -6,6 +6,7 @@ from ..models.filesystem import RangeInFile
from ..models.main import Range
from ..core.main import Step
from ..core.sdk import ContinueSDK
+from ..libs.util.create_async_task import create_async_task
import os
import re
@@ -60,9 +61,9 @@ class EditAllMatchesStep(Step):
# Search all files for a given string
range_in_files = find_all_matches_in_dir(self.pattern, self.directory or await sdk.ide.getWorkspaceDirectory())
- tasks = [asyncio.create_task(sdk.edit_file(
+ tasks = [create_async_task(sdk.edit_file(
range=range_in_file.range,
filename=range_in_file.filepath,
prompt=self.user_request
- )) for range_in_file in range_in_files]
+ ), sdk.ide.unique_id) for range_in_file in range_in_files]
await asyncio.gather(*tasks)
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
--- a/edit.gif
+++ b/edit.gif
Binary files 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
--- a/extension/media/edit.png
+++ b/extension/media/edit.png
Binary files differ
diff --git a/extension/media/explain.png b/extension/media/explain.png
index 196ab914..79e8ccc9 100644
--- a/extension/media/explain.png
+++ b/extension/media/explain.png
Binary files differ
diff --git a/extension/media/generate.png b/extension/media/generate.png
index 9d84e4ae..c16d9f9f 100644
--- a/extension/media/generate.png
+++ b/extension/media/generate.png
Binary files differ
diff --git a/extension/package-lock.json b/extension/package-lock.json
index a2ac0a04..71f4d974 100644
--- a/extension/package-lock.json
+++ b/extension/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "continue",
- "version": "0.0.145",
+ "version": "0.0.147",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "continue",
- "version": "0.0.145",
+ "version": "0.0.147",
"license": "Apache-2.0",
"dependencies": {
"@electron/rebuild": "^3.2.10",
diff --git a/extension/package.json b/extension/package.json
index 0464ba55..d9f155df 100644
--- a/extension/package.json
+++ b/extension/package.json
@@ -14,7 +14,7 @@
"displayName": "Continue",
"pricing": "Free",
"description": "The open-source coding autopilot",
- "version": "0.0.145",
+ "version": "0.0.147",
"publisher": "Continue",
"engines": {
"vscode": "^1.67.0"
@@ -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"
diff --git a/extension/react-app/src/components/Onboarding.tsx b/extension/react-app/src/components/Onboarding.tsx
new file mode 100644
index 00000000..061faba5
--- /dev/null
+++ b/extension/react-app/src/components/Onboarding.tsx
@@ -0,0 +1,115 @@
+import { useSelector } from "react-redux";
+import { RootStore } from "../redux/store";
+import React, { useState, useEffect } from "react";
+import styled from "styled-components";
+import { ArrowLeft, ArrowRight } from "@styled-icons/heroicons-outline";
+import { defaultBorderRadius } from ".";
+
+const StyledDiv = styled.div`
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-color: #1e1e1e;
+ z-index: 200;
+`;
+
+const StyledSpan = styled.span`
+ padding: 8px;
+ border-radius: ${defaultBorderRadius};
+ &:hover {
+ background-color: #ffffff33;
+ }
+`;
+
+const Onboarding = () => {
+ const [counter, setCounter] = useState(4);
+ const gifs = ["intro", "explain", "edit", "generate"];
+ const topMessages = [
+ "Welcome to Continue!",
+ "Answer coding questions",
+ "Edit in natural language",
+ "Generate files from scratch",
+ ];
+ const bottomMessages = [
+ "",
+ "Ask Continue about a part of your code to get another perspective",
+ "Highlight a section of code and instruct Continue to refactor it",
+ "Let Continue build the scaffolding of Python scripts, React components, and more",
+ ];
+
+ const vscMediaUrl = useSelector(
+ (state: RootStore) => state.config.vscMediaUrl
+ );
+
+ useEffect(() => {
+ const hasVisited = localStorage.getItem("hasVisited");
+ if (hasVisited) {
+ setCounter(4);
+ } else {
+ setCounter(0);
+ localStorage.setItem("hasVisited", "true");
+ }
+ }, []);
+
+ return (
+ <StyledDiv hidden={counter >= 4}>
+ <div
+ style={{
+ display: "grid",
+ justifyContent: "center",
+ alignItems: "center",
+ height: "100%",
+ textAlign: "center",
+ background: `linear-gradient(
+ 101.79deg,
+ #12887a66 0%,
+ #87245c66 32%,
+ #e1263766 63%,
+ #ffb21566 100%
+ )`,
+ paddingLeft: "16px",
+ paddingRight: "16px",
+ }}
+ >
+ <h1>{topMessages[counter]}</h1>
+ <div style={{ display: "flex", justifyContent: "center" }}>
+ <img
+ src={`https://github.com/continuedev/continue/blob/main/media/${gifs[counter]}.gif?raw=true`}
+ alt={topMessages[counter]}
+ />
+ </div>
+ <p>{bottomMessages[counter]}</p>
+ <p
+ style={{
+ paddingLeft: "50px",
+ paddingRight: "50px",
+ paddingBottom: "50px",
+ textAlign: "center",
+ }}
+ >
+ <div
+ style={{
+ cursor: "pointer",
+ }}
+ >
+ <StyledSpan
+ hidden={counter === 0}
+ onClick={() => setCounter((prev) => Math.max(prev - 1, 0))}
+ >
+ <ArrowLeft width="18px" strokeWidth="2px" /> Previous
+ </StyledSpan>
+ <span hidden={counter === 0}>{" | "}</span>
+ <StyledSpan onClick={() => setCounter((prev) => prev + 1)}>
+ Click to {counter === 3 || "learn how to"} use Continue{" "}
+ <ArrowRight width="18px" strokeWidth="2px" />
+ </StyledSpan>
+ </div>
+ </p>
+ </div>
+ </StyledDiv>
+ );
+};
+
+export default Onboarding;
diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx
index 646aef50..0e60e05c 100644
--- a/extension/react-app/src/tabs/gui.tsx
+++ b/extension/react-app/src/tabs/gui.tsx
@@ -23,6 +23,7 @@ import { RootStore } from "../redux/store";
import LoadingCover from "../components/LoadingCover";
import { postVscMessage } from "../vscode";
import UserInputContainer from "../components/UserInputContainer";
+import Onboarding from "../components/Onboarding";
const TopGUIDiv = styled.div`
overflow: hidden;
@@ -267,6 +268,7 @@ function GUI(props: GUIProps) {
// const iterations = useSelector(selectIterations);
return (
<>
+ <Onboarding></Onboarding>
<LoadingCover hidden={true} message="Downloading local model..." />
<TextDialog
showDialog={showFeedbackDialog}
diff --git a/extension/src/continueIdeClient.ts b/extension/src/continueIdeClient.ts
index 679d94ba..304c592b 100644
--- a/extension/src/continueIdeClient.ts
+++ b/extension/src/continueIdeClient.ts
@@ -300,7 +300,7 @@ class IdeProtocolClient {
});
const resp = await this.messenger?.sendAndReceive("openGUI", {});
const sessionId = resp.sessionId;
- console.log("New Continue session with ID: ", sessionId);
+ // console.log("New Continue session with ID: ", sessionId);
return sessionId;
}
diff --git a/media/edit.gif b/media/edit.gif
new file mode 100644
index 00000000..6780cdf7
--- /dev/null
+++ b/media/edit.gif
Binary files differ
diff --git a/media/explain.gif b/media/explain.gif
new file mode 100644
index 00000000..e74803dc
--- /dev/null
+++ b/media/explain.gif
Binary files differ
diff --git a/media/generate.gif b/media/generate.gif
new file mode 100644
index 00000000..5c1d112b
--- /dev/null
+++ b/media/generate.gif
Binary files differ
diff --git a/media/intro.gif b/media/intro.gif
new file mode 100644
index 00000000..f872dc91
--- /dev/null
+++ b/media/intro.gif
Binary files differ