summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--continuedev/src/continuedev/core/autopilot.py4
-rw-r--r--continuedev/src/continuedev/libs/util/telemetry.py4
-rw-r--r--continuedev/src/continuedev/server/ide.py30
-rw-r--r--continuedev/src/continuedev/server/ide_protocol.py4
-rw-r--r--continuedev/src/continuedev/steps/feedback.py5
-rw-r--r--extension/package-lock.json4
-rw-r--r--extension/package.json2
-rw-r--r--extension/react-app/src/tabs/gui.tsx194
-rw-r--r--extension/scripts/continuedev-0.1.1-py3-none-any.whlbin0 -> 81413 bytes
-rw-r--r--extension/src/continueIdeClient.ts9
10 files changed, 153 insertions, 103 deletions
diff --git a/continuedev/src/continuedev/core/autopilot.py b/continuedev/src/continuedev/core/autopilot.py
index 0874bbc5..703a73af 100644
--- a/continuedev/src/continuedev/core/autopilot.py
+++ b/continuedev/src/continuedev/core/autopilot.py
@@ -102,8 +102,8 @@ class Autopilot(ContinueBaseModel):
await self.update_subscribers()
async def _run_singular_step(self, step: "Step", is_future_step: bool = False) -> Coroutine[Observation, None, None]:
- capture_event(
- 'step run', {'step_name': step.name, 'params': step.dict()})
+ capture_event(self.continue_sdk.ide.unique_id, 'step run', {
+ 'step_name': step.name, 'params': step.dict()})
if not is_future_step:
# Check manual edits buffer, clear out if needed by creating a ManualEditStep
diff --git a/continuedev/src/continuedev/libs/util/telemetry.py b/continuedev/src/continuedev/libs/util/telemetry.py
index d6345c25..03ec93c6 100644
--- a/continuedev/src/continuedev/libs/util/telemetry.py
+++ b/continuedev/src/continuedev/libs/util/telemetry.py
@@ -6,7 +6,7 @@ posthog = Posthog('phc_JS6XFROuNbhJtVCEdTSYk6gl5ArRrTNMpCcguAXlSPs',
host='https://app.posthog.com')
-def capture_event(event_name, event_properties):
+def capture_event(unique_id: str, event_name, event_properties):
config = load_config('.continue/config.json')
if config.allow_anonymous_telemetry:
- posthog.capture("not distinct :(", event_name, event_properties)
+ posthog.capture(unique_id, event_name, event_properties)
diff --git a/continuedev/src/continuedev/server/ide.py b/continuedev/src/continuedev/server/ide.py
index f4ea1071..c53149d8 100644
--- a/continuedev/src/continuedev/server/ide.py
+++ b/continuedev/src/continuedev/server/ide.py
@@ -81,9 +81,29 @@ class RunCommandResponse(BaseModel):
output: str
+class UniqueIdResponse(BaseModel):
+ uniqueId: str
+
+
T = TypeVar("T", bound=BaseModel)
+class cached_property_no_none:
+ def __init__(self, func):
+ self.func = func
+
+ def __get__(self, instance, owner):
+ if instance is None:
+ return self
+ value = self.func(instance)
+ if value is not None:
+ setattr(instance, self.func.__name__, value)
+ return value
+
+ def __repr__(self):
+ return f"<cached_property_no_none '{self.func.__name__}'>"
+
+
class IdeProtocolServer(AbstractIdeProtocolServer):
websocket: WebSocket
session_manager: SessionManager
@@ -115,7 +135,7 @@ class IdeProtocolServer(AbstractIdeProtocolServer):
fileEdits = list(
map(lambda d: FileEditWithFullContents.parse_obj(d), data["fileEdits"]))
self.onFileEdits(fileEdits)
- elif message_type in ["highlightedCode", "openFiles", "readFile", "editFile", "workspaceDirectory", "getUserSecret", "runCommand"]:
+ elif message_type in ["highlightedCode", "openFiles", "readFile", "editFile", "workspaceDirectory", "getUserSecret", "runCommand", "uniqueId"]:
self.sub_queue.post(message_type, data)
else:
raise ValueError("Unknown message type", message_type)
@@ -200,10 +220,18 @@ class IdeProtocolServer(AbstractIdeProtocolServer):
resp = await self._send_and_receive_json({}, WorkspaceDirectoryResponse, "workspaceDirectory")
return resp.workspaceDirectory
+ async def get_unique_id(self) -> str:
+ resp = await self._send_and_receive_json({}, UniqueIdResponse, "uniqueId")
+ return resp.uniqueId
+
@cached_property
def workspace_directory(self) -> str:
return asyncio.run(self.getWorkspaceDirectory())
+ @cached_property_no_none
+ def unique_id(self) -> str:
+ return asyncio.run(self.get_unique_id())
+
async def getHighlightedCode(self) -> List[RangeInFile]:
resp = await self._send_and_receive_json({}, HighlightedCodeResponse, "highlightedCode")
return resp.highlightedCode
diff --git a/continuedev/src/continuedev/server/ide_protocol.py b/continuedev/src/continuedev/server/ide_protocol.py
index a937ad75..1d98f4a1 100644
--- a/continuedev/src/continuedev/server/ide_protocol.py
+++ b/continuedev/src/continuedev/server/ide_protocol.py
@@ -94,3 +94,7 @@ class AbstractIdeProtocolServer(ABC):
@abstractproperty
def workspace_directory(self) -> str:
"""Get the workspace directory"""
+
+ @abstractproperty
+ def unique_id(self) -> str:
+ """Get a unique ID for this IDE"""
diff --git a/continuedev/src/continuedev/steps/feedback.py b/continuedev/src/continuedev/steps/feedback.py
index 96081756..6f6a9b15 100644
--- a/continuedev/src/continuedev/steps/feedback.py
+++ b/continuedev/src/continuedev/steps/feedback.py
@@ -10,7 +10,8 @@ class FeedbackStep(Step):
name = "Thanks for your feedback!"
async def describe(self, models: Models):
- return f"`{self.user_input}`\n\nWe'll see your feedback and make improvements as soon as possible. If you'd like to directly email us, you can send an email to [nate@continue.dev](mailto:nate@continue.dev?subject=Feedback%20On%20Continue)."
+ return f"`{self.user_input}`\n\nWe'll see your feedback and make improvements as soon as possible. If you'd like to directly email us, you can contact [nate@continue.dev](mailto:nate@continue.dev?subject=Feedback%20On%20Continue)."
async def run(self, sdk: ContinueSDK):
- capture_event("feedback", {"feedback": self.user_input})
+ capture_event(sdk.ide.unique_id, "feedback",
+ {"feedback": self.user_input})
diff --git a/extension/package-lock.json b/extension/package-lock.json
index 6edc38f9..afa8ab2d 100644
--- a/extension/package-lock.json
+++ b/extension/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "continue",
- "version": "0.0.36",
+ "version": "0.0.38",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "continue",
- "version": "0.0.36",
+ "version": "0.0.38",
"license": "Apache-2.0",
"dependencies": {
"@electron/rebuild": "^3.2.10",
diff --git a/extension/package.json b/extension/package.json
index 91d687ab..4b86f4ea 100644
--- a/extension/package.json
+++ b/extension/package.json
@@ -14,7 +14,7 @@
"displayName": "Continue",
"pricing": "Free",
"description": "Refine code 10x faster",
- "version": "0.0.36",
+ "version": "0.0.38",
"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 55c2b763..70bab352 100644
--- a/extension/react-app/src/tabs/gui.tsx
+++ b/extension/react-app/src/tabs/gui.tsx
@@ -21,6 +21,11 @@ import {
import ComboBox from "../components/ComboBox";
import TextDialog from "../components/TextDialog";
+const MainDiv = styled.div`
+ display: grid;
+ grid-template-rows: 1fr auto;
+`;
+
let TopGUIDiv = styled.div`
display: grid;
grid-template-columns: 1fr;
@@ -39,10 +44,11 @@ const TopBar = styled.div`
display: flex;
flex-direction: row;
gap: 8px;
- justify-content: center;
+ justify-content: right;
padding: 8px;
align-items: center;
- border-bottom: 0.1px solid gray;
+ margin-top: 8px;
+ border-top: 0.1px solid gray;
`;
interface GUIProps {
@@ -294,101 +300,103 @@ function GUI(props: GUIProps) {
setShowFeedbackDialog(false);
}}
></TextDialog>
- <TopGUIDiv
- ref={topGuiDivRef}
- onKeyDown={(e) => {
- if (e.key === "Enter" && e.ctrlKey) {
- onMainTextInput();
- }
- }}
- >
- <TopBar>
- <a href="https://continue.dev/docs" className="no-underline">
- <HeaderButton style={{ padding: "3px" }}>
- Continue Docs
- <BookOpen size="1.6em" />
- </HeaderButton>
- </a>
- <HeaderButton
- style={{ padding: "3px" }}
- onClick={() => {
- // Set dialog open
- setShowFeedbackDialog(true);
- }}
- >
- Feedback
- <ChatBubbleOvalLeftEllipsis size="1.6em" />
- </HeaderButton>
- <HeaderButton
- onClick={() => {
- client?.sendClear();
+ <MainDiv>
+ <TopGUIDiv
+ ref={topGuiDivRef}
+ onKeyDown={(e) => {
+ if (e.key === "Enter" && e.ctrlKey) {
+ onMainTextInput();
+ }
+ }}
+ >
+ {typeof client === "undefined" && (
+ <>
+ <Loader></Loader>
+ <p style={{ textAlign: "center" }}>
+ Trying to reconnect with server...
+ </p>
+ </>
+ )}
+ {history?.timeline.map((node: HistoryNode, index: number) => {
+ return (
+ <StepContainer
+ key={index}
+ onUserInput={(input: string) => {
+ onStepUserInput(input, index);
+ }}
+ inFuture={index > history?.current_index}
+ historyNode={node}
+ onRefinement={(input: string) => {
+ client?.sendRefinementInput(input, index);
+ }}
+ onReverse={() => {
+ client?.reverseToIndex(index);
+ }}
+ onRetry={() => {
+ client?.retryAtIndex(index);
+ setWaitingForSteps(true);
+ }}
+ onDelete={() => {
+ client?.deleteAtIndex(index);
+ }}
+ />
+ );
+ })}
+ {waitingForSteps && <Loader></Loader>}
+
+ <div>
+ {userInputQueue.map((input) => {
+ return <UserInputQueueItem>{input}</UserInputQueueItem>;
+ })}
+ </div>
+
+ <ComboBox
+ disabled={
+ history?.timeline.length
+ ? history.timeline[history.current_index].step.name ===
+ "Waiting for user confirmation"
+ : false
+ }
+ ref={mainTextInputRef}
+ onEnter={(e) => {
+ onMainTextInput();
+ e.stopPropagation();
+ e.preventDefault();
}}
- style={{ padding: "3px" }}
- >
- Clear History
- <Trash size="1.6em" />
- </HeaderButton>
- </TopBar>
+ onInputValueChange={() => {}}
+ items={availableSlashCommands}
+ />
+ <ContinueButton onClick={onMainTextInput} />
- {typeof client === "undefined" && (
- <>
- <Loader></Loader>
- <p style={{ textAlign: "center" }}>
- Trying to reconnect with server...
- </p>
- </>
- )}
- {history?.timeline.map((node: HistoryNode, index: number) => {
- return (
- <StepContainer
- key={index}
- onUserInput={(input: string) => {
- onStepUserInput(input, index);
+ <TopBar>
+ <a href="https://continue.dev/docs" className="no-underline">
+ <HeaderButton style={{ padding: "3px" }}>
+ Continue Docs
+ <BookOpen size="1.6em" />
+ </HeaderButton>
+ </a>
+ <HeaderButton
+ style={{ padding: "3px" }}
+ onClick={() => {
+ // Set dialog open
+ setShowFeedbackDialog(true);
}}
- inFuture={index > history?.current_index}
- historyNode={node}
- onRefinement={(input: string) => {
- client?.sendRefinementInput(input, index);
- }}
- onReverse={() => {
- client?.reverseToIndex(index);
- }}
- onRetry={() => {
- client?.retryAtIndex(index);
- setWaitingForSteps(true);
- }}
- onDelete={() => {
- client?.deleteAtIndex(index);
+ >
+ Feedback
+ <ChatBubbleOvalLeftEllipsis size="1.6em" />
+ </HeaderButton>
+ <HeaderButton
+ onClick={() => {
+ client?.sendClear();
}}
- />
- );
- })}
- {waitingForSteps && <Loader></Loader>}
-
- <div>
- {userInputQueue.map((input) => {
- return <UserInputQueueItem>{input}</UserInputQueueItem>;
- })}
- </div>
-
- <ComboBox
- disabled={
- history?.timeline.length
- ? history.timeline[history.current_index].step.name ===
- "Waiting for user confirmation"
- : false
- }
- ref={mainTextInputRef}
- onEnter={(e) => {
- onMainTextInput();
- e.stopPropagation();
- e.preventDefault();
- }}
- onInputValueChange={() => {}}
- items={availableSlashCommands}
- />
- <ContinueButton onClick={onMainTextInput} />
- </TopGUIDiv>
+ style={{ padding: "3px" }}
+ >
+ Clear History
+ <Trash size="1.6em" />
+ </HeaderButton>
+ </TopBar>
+ </TopGUIDiv>
+ </MainDiv>
</>
);
}
diff --git a/extension/scripts/continuedev-0.1.1-py3-none-any.whl b/extension/scripts/continuedev-0.1.1-py3-none-any.whl
new file mode 100644
index 00000000..b3e8229a
--- /dev/null
+++ b/extension/scripts/continuedev-0.1.1-py3-none-any.whl
Binary files differ
diff --git a/extension/src/continueIdeClient.ts b/extension/src/continueIdeClient.ts
index 3308068a..16941c70 100644
--- a/extension/src/continueIdeClient.ts
+++ b/extension/src/continueIdeClient.ts
@@ -77,6 +77,11 @@ class IdeProtocolClient {
workspaceDirectory: this.getWorkspaceDirectory(),
});
break;
+ case "uniqueId":
+ this.messenger?.send("uniqueId", {
+ uniqueId: this.getUniqueId(),
+ });
+ break;
case "getUserSecret":
this.messenger?.send("getUserSecret", {
value: await this.getUserSecret(data.key),
@@ -128,6 +133,10 @@ class IdeProtocolClient {
return vscode.workspace.workspaceFolders[0].uri.fsPath;
}
+ getUniqueId() {
+ return vscode.env.machineId;
+ }
+
// ------------------------------------ //
// On message handlers