summaryrefslogtreecommitdiff
path: root/extension/react-app/src/redux
diff options
context:
space:
mode:
authorNate Sesti <sestinj@gmail.com>2023-05-23 23:45:12 -0400
committerNate Sesti <sestinj@gmail.com>2023-05-23 23:45:12 -0400
commitf53768612b1e2268697b5444e502032ef9f3fb3c (patch)
tree4ed49b73e6bd3c2f8fceffa9643973033f87af95 /extension/react-app/src/redux
downloadsncontinue-f53768612b1e2268697b5444e502032ef9f3fb3c.tar.gz
sncontinue-f53768612b1e2268697b5444e502032ef9f3fb3c.tar.bz2
sncontinue-f53768612b1e2268697b5444e502032ef9f3fb3c.zip
copying from old repo
Diffstat (limited to 'extension/react-app/src/redux')
-rw-r--r--extension/react-app/src/redux/hooks.ts21
-rw-r--r--extension/react-app/src/redux/selectors/chatSelectors.ts11
-rw-r--r--extension/react-app/src/redux/selectors/debugContextSelectors.ts29
-rw-r--r--extension/react-app/src/redux/selectors/miscSelectors.ts5
-rw-r--r--extension/react-app/src/redux/slices/chatSlice.ts93
-rw-r--r--extension/react-app/src/redux/slices/configSlice.ts45
-rw-r--r--extension/react-app/src/redux/slices/debugContexSlice.ts149
-rw-r--r--extension/react-app/src/redux/slices/miscSlice.ts16
-rw-r--r--extension/react-app/src/redux/store.ts43
9 files changed, 412 insertions, 0 deletions
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;