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/react-app/src/redux/hooks.ts | 21 +++ .../react-app/src/redux/selectors/chatSelectors.ts | 11 ++ .../src/redux/selectors/debugContextSelectors.ts | 29 ++++ .../react-app/src/redux/selectors/miscSelectors.ts | 5 + extension/react-app/src/redux/slices/chatSlice.ts | 93 +++++++++++++ .../react-app/src/redux/slices/configSlice.ts | 45 +++++++ .../react-app/src/redux/slices/debugContexSlice.ts | 149 +++++++++++++++++++++ extension/react-app/src/redux/slices/miscSlice.ts | 16 +++ extension/react-app/src/redux/store.ts | 43 ++++++ 9 files changed, 412 insertions(+) create mode 100644 extension/react-app/src/redux/hooks.ts create mode 100644 extension/react-app/src/redux/selectors/chatSelectors.ts create mode 100644 extension/react-app/src/redux/selectors/debugContextSelectors.ts create mode 100644 extension/react-app/src/redux/selectors/miscSelectors.ts create mode 100644 extension/react-app/src/redux/slices/chatSlice.ts create mode 100644 extension/react-app/src/redux/slices/configSlice.ts create mode 100644 extension/react-app/src/redux/slices/debugContexSlice.ts create mode 100644 extension/react-app/src/redux/slices/miscSlice.ts create mode 100644 extension/react-app/src/redux/store.ts (limited to 'extension/react-app/src/redux') diff --git a/extension/react-app/src/redux/hooks.ts b/extension/react-app/src/redux/hooks.ts new file mode 100644 index 00000000..a6aef869 --- /dev/null +++ b/extension/react-app/src/redux/hooks.ts @@ -0,0 +1,21 @@ +import { useCallback } from "react"; +import { useDispatch, useSelector } from "react-redux"; +import { RootStore } from "./store"; +import { selectDebugContextValue } from "./selectors/debugContextSelectors"; +import { updateValue } from "./slices/debugContexSlice"; +import { SerializedDebugContext } from "../../../src/client"; + +export function useDebugContextValue( + key: keyof SerializedDebugContext, + defaultValue: any +): [any, (value: any) => void] { + const dispatch = useDispatch(); + const state = + useSelector((state: RootStore) => selectDebugContextValue(state, key)) || + defaultValue; + const boundAction = useCallback( + (value: any) => dispatch(updateValue({ key, value })), + [dispatch, key] + ); + return [state, boundAction]; +} diff --git a/extension/react-app/src/redux/selectors/chatSelectors.ts b/extension/react-app/src/redux/selectors/chatSelectors.ts new file mode 100644 index 00000000..51e8a636 --- /dev/null +++ b/extension/react-app/src/redux/selectors/chatSelectors.ts @@ -0,0 +1,11 @@ +import { RootStore } from "../store"; + +const selectChatMessages = (state: RootStore) => { + return state.chat.messages; +}; + +const selectIsStreaming = (state: RootStore) => { + return state.chat.isStreaming; +}; + +export { selectChatMessages, selectIsStreaming }; diff --git a/extension/react-app/src/redux/selectors/debugContextSelectors.ts b/extension/react-app/src/redux/selectors/debugContextSelectors.ts new file mode 100644 index 00000000..89201bb7 --- /dev/null +++ b/extension/react-app/src/redux/selectors/debugContextSelectors.ts @@ -0,0 +1,29 @@ +import { RootStore } from "../store"; + +const selectDebugContext = (state: RootStore) => { + return { + ...state.debugState.debugContext, + rangesInFiles: state.debugState.debugContext.rangesInFiles.filter( + (_, index) => state.debugState.rangesMask[index] + ), + }; +}; + +const selectAllRangesInFiles = (state: RootStore) => { + return state.debugState.debugContext.rangesInFiles; +}; + +const selectRangesMask = (state: RootStore) => { + return state.debugState.rangesMask; +}; + +const selectDebugContextValue = (state: RootStore, key: string) => { + return (state.debugState.debugContext as any)[key]; +}; + +export { + selectDebugContext, + selectDebugContextValue, + selectAllRangesInFiles, + selectRangesMask, +}; diff --git a/extension/react-app/src/redux/selectors/miscSelectors.ts b/extension/react-app/src/redux/selectors/miscSelectors.ts new file mode 100644 index 00000000..7dbaed09 --- /dev/null +++ b/extension/react-app/src/redux/selectors/miscSelectors.ts @@ -0,0 +1,5 @@ +import { RootStore } from "../store"; + +const selectHighlightedCode = (state: RootStore) => state.misc.highlightedCode; + +export { selectHighlightedCode }; diff --git a/extension/react-app/src/redux/slices/chatSlice.ts b/extension/react-app/src/redux/slices/chatSlice.ts new file mode 100644 index 00000000..848cccd4 --- /dev/null +++ b/extension/react-app/src/redux/slices/chatSlice.ts @@ -0,0 +1,93 @@ +import { createSlice } from "@reduxjs/toolkit"; +import { ChatMessage, RootStore } from "../store"; + +export const chatSlice = createSlice({ + name: "chat", + initialState: { + messages: [], + isStreaming: false, + } as RootStore["chat"], + reducers: { + addMessage: ( + state, + action: { + type: string; + payload: ChatMessage; + } + ) => { + return { + ...state, + messages: [...state.messages, action.payload], + }; + }, + setIsStreaming: (state, action) => { + return { + ...state, + isStreaming: action.payload, + }; + }, + streamUpdate: (state, action) => { + if (!state.isStreaming) { + return { + ...state, + messages: [ + ...state.messages, + { + role: "assistant", + content: action.payload, + }, + ], + isStreaming: true, + }; + } else { + let lastMessage = state.messages[state.messages.length - 1]; + if (lastMessage.role !== "assistant") { + return { + ...state, + messages: [ + ...state.messages, + { + role: "assistant", + content: action.payload, + }, + ], + isStreaming: true, + }; + } + return { + ...state, + messages: [ + ...state.messages.slice(0, state.messages.length - 1), + { + ...lastMessage, + content: lastMessage.content + action.payload, + }, + ], + isStreaming: true, + }; + } + }, + closeStream: (state) => { + return { + ...state, + isStreaming: false, + }; + }, + clearChat: (state) => { + return { + ...state, + messages: [], + isStreaming: false, + }; + }, + }, +}); + +export const { + addMessage, + streamUpdate, + closeStream, + clearChat, + setIsStreaming, +} = chatSlice.actions; +export default chatSlice.reducer; diff --git a/extension/react-app/src/redux/slices/configSlice.ts b/extension/react-app/src/redux/slices/configSlice.ts new file mode 100644 index 00000000..a6a641e6 --- /dev/null +++ b/extension/react-app/src/redux/slices/configSlice.ts @@ -0,0 +1,45 @@ +import { createSlice } from "@reduxjs/toolkit"; +import { RootStore } from "../store"; + +export const configSlice = createSlice({ + name: "config", + initialState: { + apiUrl: "http://localhost:8000", + } as RootStore["config"], + reducers: { + setWorkspacePath: ( + state: RootStore["config"], + action: { type: string; payload: string } + ) => { + return { + ...state, + workspacePath: action.payload, + }; + }, + setApiUrl: ( + state: RootStore["config"], + action: { type: string; payload: string } + ) => ({ + ...state, + apiUrl: action.payload, + }), + setVscMachineId: ( + state: RootStore["config"], + action: { type: string; payload: string } + ) => ({ + ...state, + vscMachineId: action.payload, + }), + setSessionId: ( + state: RootStore["config"], + action: { type: string; payload: string } + ) => ({ + ...state, + sessionId: action.payload, + }), + }, +}); + +export const { setVscMachineId, setApiUrl, setWorkspacePath, setSessionId } = + configSlice.actions; +export default configSlice.reducer; diff --git a/extension/react-app/src/redux/slices/debugContexSlice.ts b/extension/react-app/src/redux/slices/debugContexSlice.ts new file mode 100644 index 00000000..647440d5 --- /dev/null +++ b/extension/react-app/src/redux/slices/debugContexSlice.ts @@ -0,0 +1,149 @@ +import { createSlice } from "@reduxjs/toolkit"; +import { RangeInFile, SerializedDebugContext } from "../../../../src/client"; +import { RootStore } from "../store"; + +export const debugStateSlice = createSlice({ + name: "debugState", + initialState: { + debugContext: { + rangesInFiles: [], + filesystem: {}, + traceback: undefined, + description: undefined, + }, + rangesMask: [], + } as RootStore["debugState"], + reducers: { + updateValue: ( + state: RootStore["debugState"], + action: { + type: string; + payload: { key: keyof SerializedDebugContext; value: any }; + } + ) => { + return { + ...state, + debugContext: { + ...state.debugContext, + [action.payload.key]: action.payload.value, + }, + }; + }, + addRangeInFile: ( + state: RootStore["debugState"], + action: { + type: string; + payload: { + rangeInFile: RangeInFile; + canUpdateLast: boolean; + }; + } + ) => { + let rangesInFiles = state.debugContext.rangesInFiles; + // If identical to existing range, don't add. Ideally you check for overlap of ranges. + for (let range of rangesInFiles) { + if ( + range.filepath === action.payload.rangeInFile.filepath && + range.range.start.line === + action.payload.rangeInFile.range.start.line && + range.range.end.line === action.payload.rangeInFile.range.end.line + ) { + return state; + } + } + + if ( + action.payload.canUpdateLast && + rangesInFiles.length > 0 && + rangesInFiles[rangesInFiles.length - 1].filepath === + action.payload.rangeInFile.filepath + ) { + return { + ...state, + debugContext: { + ...state.debugContext, + rangesInFiles: [ + ...rangesInFiles.slice(0, rangesInFiles.length - 1), + action.payload.rangeInFile, + ], + }, + }; + } else { + return { + ...state, + debugContext: { + ...state.debugContext, + rangesInFiles: [ + ...state.debugContext.rangesInFiles, + action.payload.rangeInFile, + ], + }, + rangesMask: [...state.rangesMask, true], + }; + } + }, + deleteRangeInFileAt: ( + state: RootStore["debugState"], + action: { + type: string; + payload: number; + } + ) => { + return { + ...state, + debugContext: { + ...state.debugContext, + rangesInFiles: state.debugContext.rangesInFiles.filter( + (_, index) => index !== action.payload + ), + }, + rangesMask: state.rangesMask.filter( + (_, index) => index !== action.payload + ), + }; + }, + toggleSelectionAt: ( + state: RootStore["debugState"], + action: { + type: string; + payload: number; + } + ) => { + return { + ...state, + rangesMask: state.rangesMask.map((_, index) => + index === action.payload + ? !state.rangesMask[index] + : state.rangesMask[index] + ), + }; + }, + updateFileSystem: ( + state: RootStore["debugState"], + action: { + type: string; + payload: { [filepath: string]: string }; + } + ) => { + return { + ...state, + debugContext: { + ...state.debugContext, + filesystem: { + ...state.debugContext.filesystem, + ...action.payload, + }, + }, + }; + }, + }, +}); + +export const { + updateValue, + updateFileSystem, + addRangeInFile, + deleteRangeInFileAt, + toggleSelectionAt, +} = debugStateSlice.actions; +export default debugStateSlice.reducer; diff --git a/extension/react-app/src/redux/slices/miscSlice.ts b/extension/react-app/src/redux/slices/miscSlice.ts new file mode 100644 index 00000000..c59cc4eb --- /dev/null +++ b/extension/react-app/src/redux/slices/miscSlice.ts @@ -0,0 +1,16 @@ +import { createSlice } from "@reduxjs/toolkit"; + +export const miscSlice = createSlice({ + name: "misc", + initialState: { + highlightedCode: "", + }, + reducers: { + setHighlightedCode: (state, action) => { + state.highlightedCode = action.payload; + }, + }, +}); + +export const { setHighlightedCode } = miscSlice.actions; +export default miscSlice.reducer; diff --git a/extension/react-app/src/redux/store.ts b/extension/react-app/src/redux/store.ts new file mode 100644 index 00000000..f9eb0517 --- /dev/null +++ b/extension/react-app/src/redux/store.ts @@ -0,0 +1,43 @@ +import { configureStore } from "@reduxjs/toolkit"; +import debugStateReducer from "./slices/debugContexSlice"; +import chatReducer from "./slices/chatSlice"; +import configReducer from "./slices/configSlice"; +import miscReducer from "./slices/miscSlice"; +import { RangeInFile, SerializedDebugContext } from "../../../src/client"; + +export interface ChatMessage { + role: "system" | "user" | "assistant"; + content: string; +} + +export interface RootStore { + debugState: { + debugContext: SerializedDebugContext; + rangesMask: boolean[]; + }; + config: { + workspacePath: string | undefined; + apiUrl: string; + vscMachineId: string | undefined; + sessionId: string | undefined; + sessionStarted: number | undefined; + }; + chat: { + messages: ChatMessage[]; + isStreaming: boolean; + }; + misc: { + highlightedCode: RangeInFile | undefined; + }; +} + +const store = configureStore({ + reducer: { + debugState: debugStateReducer, + chat: chatReducer, + config: configReducer, + misc: miscReducer, + }, +}); + +export default store; -- cgit v1.2.3-70-g09d2 From 5b06f7703dc0ad0855d6fd908c2aad66d73ee412 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Thu, 22 Jun 2023 17:02:50 -0700 Subject: added continue retro button icon --- extension/react-app/src/components/ContinueButton.tsx | 13 +++++++++++-- extension/react-app/src/components/DebugPanel.tsx | 2 ++ extension/react-app/src/redux/slices/configSlice.ts | 16 ++++++++++++++-- extension/react-app/src/redux/store.ts | 1 + extension/src/debugPanel.ts | 4 ++++ 5 files changed, 32 insertions(+), 4 deletions(-) (limited to 'extension/react-app/src/redux') diff --git a/extension/react-app/src/components/ContinueButton.tsx b/extension/react-app/src/components/ContinueButton.tsx index c6117bf9..ef6719b7 100644 --- a/extension/react-app/src/components/ContinueButton.tsx +++ b/extension/react-app/src/components/ContinueButton.tsx @@ -1,6 +1,8 @@ import styled, { keyframes } from "styled-components"; import { Button } from "."; import { Play } from "@styled-icons/heroicons-outline"; +import { useSelector } from "react-redux"; +import { RootStore } from "../redux/store"; let StyledButton = styled(Button)` margin: auto; @@ -25,14 +27,21 @@ let StyledButton = styled(Button)` `; function ContinueButton(props: { onClick?: () => void; hidden?: boolean }) { + const vscMediaUrl = useSelector( + (state: RootStore) => state.config.vscMediaUrl + ); + return ( ); diff --git a/extension/react-app/src/components/DebugPanel.tsx b/extension/react-app/src/components/DebugPanel.tsx index 30f38779..94dbac9e 100644 --- a/extension/react-app/src/components/DebugPanel.tsx +++ b/extension/react-app/src/components/DebugPanel.tsx @@ -6,6 +6,7 @@ import { setApiUrl, setVscMachineId, setSessionId, + setVscMediaUrl, } from "../redux/slices/configSlice"; import { setHighlightedCode } from "../redux/slices/miscSlice"; import { updateFileSystem } from "../redux/slices/debugContexSlice"; @@ -37,6 +38,7 @@ function DebugPanel(props: DebugPanelProps) { dispatch(setApiUrl(event.data.apiUrl)); dispatch(setVscMachineId(event.data.vscMachineId)); dispatch(setSessionId(event.data.sessionId)); + dispatch(setVscMediaUrl(event.data.vscMediaUrl)); break; case "highlightedCode": dispatch(setHighlightedCode(event.data.rangeInFile)); diff --git a/extension/react-app/src/redux/slices/configSlice.ts b/extension/react-app/src/redux/slices/configSlice.ts index a6a641e6..1b107bed 100644 --- a/extension/react-app/src/redux/slices/configSlice.ts +++ b/extension/react-app/src/redux/slices/configSlice.ts @@ -37,9 +37,21 @@ export const configSlice = createSlice({ ...state, sessionId: action.payload, }), + setVscMediaUrl: ( + state: RootStore["config"], + action: { type: string; payload: string } + ) => ({ + ...state, + vscMediaUrl: action.payload, + }), }, }); -export const { setVscMachineId, setApiUrl, setWorkspacePath, setSessionId } = - configSlice.actions; +export const { + setVscMachineId, + setApiUrl, + setWorkspacePath, + setSessionId, + setVscMediaUrl, +} = configSlice.actions; export default configSlice.reducer; diff --git a/extension/react-app/src/redux/store.ts b/extension/react-app/src/redux/store.ts index f9eb0517..a5eef4ba 100644 --- a/extension/react-app/src/redux/store.ts +++ b/extension/react-app/src/redux/store.ts @@ -21,6 +21,7 @@ export interface RootStore { vscMachineId: string | undefined; sessionId: string | undefined; sessionStarted: number | undefined; + vscMediaUrl: string | undefined; }; chat: { messages: ChatMessage[]; diff --git a/extension/src/debugPanel.ts b/extension/src/debugPanel.ts index 232203b9..b0db590a 100644 --- a/extension/src/debugPanel.ts +++ b/extension/src/debugPanel.ts @@ -136,6 +136,9 @@ export function setupDebugPanel( let extensionUri = getExtensionUri(); let scriptUri: string; let styleMainUri: string; + let vscMediaUrl: string = debugPanelWebview + .asWebviewUri(vscode.Uri.joinPath(extensionUri, "react-app/dist")) + .toString(); const isProduction = true; // context?.extensionMode === vscode.ExtensionMode.Development; if (!isProduction) { @@ -226,6 +229,7 @@ export function setupDebugPanel( vscMachineId: vscode.env.machineId, apiUrl: getContinueServerUrl(), sessionId, + vscMediaUrl, }); // // Listen for changes to server URL in settings -- cgit v1.2.3-70-g09d2 From 69784df58a7b0f6aaebd6eb7f7c260a63fc36055 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Tue, 27 Jun 2023 23:35:49 -0700 Subject: use a more esoteric port than 8000 (65432) --- continuedev/src/continuedev/server/main.py | 3 ++- extension/DEV_README.md | 4 ++-- extension/config/dev_config.json | 2 +- extension/package.json | 2 +- extension/react-app/src/redux/slices/configSlice.ts | 2 +- extension/src/activation/environmentSetup.ts | 2 +- extension/src/bridge.ts | 4 ++-- extension/src/suggestions.ts | 16 ++++++++-------- 8 files changed, 18 insertions(+), 17 deletions(-) (limited to 'extension/react-app/src/redux') diff --git a/continuedev/src/continuedev/server/main.py b/continuedev/src/continuedev/server/main.py index fb6ead02..f4d82903 100644 --- a/continuedev/src/continuedev/server/main.py +++ b/continuedev/src/continuedev/server/main.py @@ -31,7 +31,8 @@ def health(): # add cli arg for server port parser = argparse.ArgumentParser() -parser.add_argument("-p", "--port", help="server port", type=int, default=8000) +parser.add_argument("-p", "--port", help="server port", + type=int, default=65432) args = parser.parse_args() diff --git a/extension/DEV_README.md b/extension/DEV_README.md index fc91fe32..cf168cb3 100644 --- a/extension/DEV_README.md +++ b/extension/DEV_README.md @@ -4,6 +4,6 @@ This is the Continue VS Code Extension. Its primary jobs are 1. Implement the IDE side of the Continue IDE protocol, allowing a Continue server to interact natively in an IDE. This happens in `src/continueIdeClient.ts`. 2. Open the Continue React app in a side panel. The React app's source code lives in the `react-app` directory. The panel is opened by the `continue.openContinueGUI` command, as defined in `src/commands.ts`. -3. Run a Continue server in the background, which connects to both the IDE protocol and the React app. The server is launched in `src/activation/environmentSetup.ts` by calling Python code that lives in `scripts/` (unless extension settings define a server URL other than localhost:8000, in which case the extension will just connect to that). +3. Run a Continue server in the background, which connects to both the IDE protocol and the React app. The server is launched in `src/activation/environmentSetup.ts` by calling Python code that lives in `scripts/` (unless extension settings define a server URL other than localhost:65432, in which case the extension will just connect to that). -1. Open Continue \ No newline at end of file +4. Open Continue diff --git a/extension/config/dev_config.json b/extension/config/dev_config.json index a664d524..b4b9993e 100644 --- a/extension/config/dev_config.json +++ b/extension/config/dev_config.json @@ -1,3 +1,3 @@ { - "API_URL": "http://localhost:8000" + "API_URL": "http://localhost:65432" } diff --git a/extension/package.json b/extension/package.json index ceba8698..447eaeba 100644 --- a/extension/package.json +++ b/extension/package.json @@ -50,7 +50,7 @@ }, "continue.serverUrl": { "type": "string", - "default": "http://localhost:8000", + "default": "http://localhost:65432", "description": "The URL of the Continue server to use." }, "continue.OPENAI_API_KEY": { diff --git a/extension/react-app/src/redux/slices/configSlice.ts b/extension/react-app/src/redux/slices/configSlice.ts index 1b107bed..229c9c5c 100644 --- a/extension/react-app/src/redux/slices/configSlice.ts +++ b/extension/react-app/src/redux/slices/configSlice.ts @@ -4,7 +4,7 @@ import { RootStore } from "../store"; export const configSlice = createSlice({ name: "config", initialState: { - apiUrl: "http://localhost:8000", + apiUrl: "http://localhost:65432", } as RootStore["config"], reducers: { setWorkspacePath: ( diff --git a/extension/src/activation/environmentSetup.ts b/extension/src/activation/environmentSetup.ts index e4f8d6ed..168c79ad 100644 --- a/extension/src/activation/environmentSetup.ts +++ b/extension/src/activation/environmentSetup.ts @@ -218,7 +218,7 @@ export async function startContinuePythonServer() { // Check vscode settings const serverUrl = getContinueServerUrl(); - if (serverUrl !== "http://localhost:8000") { + if (serverUrl !== "http://localhost:65432") { return; } diff --git a/extension/src/bridge.ts b/extension/src/bridge.ts index b0fdafa7..92ba4044 100644 --- a/extension/src/bridge.ts +++ b/extension/src/bridge.ts @@ -48,7 +48,7 @@ export function get_api_url() { if (config.API_URL) { return config.API_URL; } - return "http://localhost:8000"; + return "http://localhost:65432"; } const API_URL = get_api_url(); @@ -62,7 +62,7 @@ export function getContinueServerUrl() { } return ( vscode.workspace.getConfiguration("continue").get("serverUrl") || - "http://localhost:8000" + "http://localhost:65432" ); } diff --git a/extension/src/suggestions.ts b/extension/src/suggestions.ts index 6e5f52ac..c9e29ed5 100644 --- a/extension/src/suggestions.ts +++ b/extension/src/suggestions.ts @@ -37,18 +37,18 @@ const oldDecorationType = vscode.window.createTextEditorDecorationType({ const newSelDecorationType = vscode.window.createTextEditorDecorationType({ backgroundColor: "rgb(0, 255, 0, 0.25)", isWholeLine: true, - after: { - contentText: "Press ctrl+shift+enter to accept", - margin: "0 0 0 1em", - }, + // after: { + // contentText: "Press ctrl+shift+enter to accept", + // margin: "0 0 0 1em", + // }, }); const oldSelDecorationType = vscode.window.createTextEditorDecorationType({ backgroundColor: "rgb(255, 0, 0, 0.25)", isWholeLine: true, - after: { - contentText: "Press ctrl+shift+enter to reject", - margin: "0 0 0 1em", - }, + // after: { + // contentText: "Press ctrl+shift+enter to reject", + // margin: "0 0 0 1em", + // }, }); export function rerenderDecorations(editorUri: string) { -- cgit v1.2.3-70-g09d2 From 52982ef8d8612209dfd32d5688e45ed110ffefa2 Mon Sep 17 00:00:00 2001 From: Ty Dunn Date: Thu, 29 Jun 2023 16:27:40 -0700 Subject: close on data collection --- extension/react-app/src/components/DebugPanel.tsx | 2 ++ .../react-app/src/redux/slices/configSlice.ts | 8 +++++++ extension/react-app/src/redux/store.ts | 1 + extension/react-app/src/tabs/gui.tsx | 25 ++++++++++++++++------ 4 files changed, 29 insertions(+), 7 deletions(-) (limited to 'extension/react-app/src/redux') diff --git a/extension/react-app/src/components/DebugPanel.tsx b/extension/react-app/src/components/DebugPanel.tsx index 94dbac9e..fffb6c6e 100644 --- a/extension/react-app/src/components/DebugPanel.tsx +++ b/extension/react-app/src/components/DebugPanel.tsx @@ -7,6 +7,7 @@ import { setVscMachineId, setSessionId, setVscMediaUrl, + setDataSwitchOn, } from "../redux/slices/configSlice"; import { setHighlightedCode } from "../redux/slices/miscSlice"; import { updateFileSystem } from "../redux/slices/debugContexSlice"; @@ -39,6 +40,7 @@ function DebugPanel(props: DebugPanelProps) { dispatch(setVscMachineId(event.data.vscMachineId)); dispatch(setSessionId(event.data.sessionId)); dispatch(setVscMediaUrl(event.data.vscMediaUrl)); + dispatch(setDataSwitchOn(event.data.dataSwitchOn)); break; case "highlightedCode": dispatch(setHighlightedCode(event.data.rangeInFile)); diff --git a/extension/react-app/src/redux/slices/configSlice.ts b/extension/react-app/src/redux/slices/configSlice.ts index 229c9c5c..57c4f860 100644 --- a/extension/react-app/src/redux/slices/configSlice.ts +++ b/extension/react-app/src/redux/slices/configSlice.ts @@ -44,6 +44,13 @@ export const configSlice = createSlice({ ...state, vscMediaUrl: action.payload, }), + setDataSwitchOn: ( + state: RootStore["config"], + action: { type: string; payload: boolean } + ) => ({ + ...state, + dataSwitchOn: action.payload, + }) }, }); @@ -53,5 +60,6 @@ export const { setWorkspacePath, setSessionId, setVscMediaUrl, + setDataSwitchOn } = configSlice.actions; export default configSlice.reducer; diff --git a/extension/react-app/src/redux/store.ts b/extension/react-app/src/redux/store.ts index a5eef4ba..b6eb55b3 100644 --- a/extension/react-app/src/redux/store.ts +++ b/extension/react-app/src/redux/store.ts @@ -22,6 +22,7 @@ export interface RootStore { sessionId: string | undefined; sessionStarted: number | undefined; vscMediaUrl: string | undefined; + dataSwitchOn: boolean | undefined; }; chat: { messages: ChatMessage[]; diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx index 8d21a457..292977c7 100644 --- a/extension/react-app/src/tabs/gui.tsx +++ b/extension/react-app/src/tabs/gui.tsx @@ -19,6 +19,7 @@ import { usePostHog } from "posthog-js/react"; import { useSelector } from "react-redux"; import { RootStore } from "../redux/store"; import LoadingCover from "../components/LoadingCover"; +import { postVscMessage } from "../vscode"; const TopGUIDiv = styled.div` overflow: hidden; @@ -54,6 +55,16 @@ function GUI(props: GUIProps) { const vscMachineId = useSelector( (state: RootStore) => state.config.vscMachineId ); + const [dataSwitchChecked, setDataSwitchChecked] = useState(false); + const dataSwitchOn = useSelector( + (state: RootStore) => state.config.dataSwitchOn + ) + + useEffect(() => { + if (typeof dataSwitchOn !== "undefined") { + setDataSwitchChecked(dataSwitchOn) + } + }, [dataSwitchOn]) const [usingFastModel, setUsingFastModel] = useState(false); const [waitingForSteps, setWaitingForSteps] = useState(false); @@ -61,7 +72,6 @@ function GUI(props: GUIProps) { const [availableSlashCommands, setAvailableSlashCommands] = useState< { name: string; description: string }[] >([]); - const [dataSwitchChecked, setDataSwitchChecked] = useState(false); const [showDataSharingInfo, setShowDataSharingInfo] = useState(false); const [stepsOpen, setStepsOpen] = useState([ true, @@ -538,15 +548,15 @@ function GUI(props: GUIProps) { }} hidden={!showDataSharingInfo} > - By turning on this switch, you signal that you would contribute this - software development data to a publicly accessible, open-source dataset - in the future. + By turning on this switch, you will begin collecting accepted and + rejected suggestions in .continue/suggestions.json. This data is + stored locally on your machine and not sent anywhere.

{dataSwitchChecked - ? "No data is being collected. In the future, you would be contributing data" - : "No data is being collected. In the future, your data would not be shared"} + ? "👍 Data is being collected" + : "👎 No data is being collected"}