diff options
author | Nate Sesti <sestinj@gmail.com> | 2023-05-23 23:45:12 -0400 |
---|---|---|
committer | Nate Sesti <sestinj@gmail.com> | 2023-05-23 23:45:12 -0400 |
commit | 27ecedb02ef79ce53bf533e016b00462c44541be (patch) | |
tree | 402305113b6f04c3e3b3563b68d32de5ff1c69c8 /extension/react-app/src/redux | |
download | sncontinue-27ecedb02ef79ce53bf533e016b00462c44541be.tar.gz sncontinue-27ecedb02ef79ce53bf533e016b00462c44541be.tar.bz2 sncontinue-27ecedb02ef79ce53bf533e016b00462c44541be.zip |
copying from old repo
Diffstat (limited to 'extension/react-app/src/redux')
-rw-r--r-- | extension/react-app/src/redux/hooks.ts | 21 | ||||
-rw-r--r-- | extension/react-app/src/redux/selectors/chatSelectors.ts | 11 | ||||
-rw-r--r-- | extension/react-app/src/redux/selectors/debugContextSelectors.ts | 29 | ||||
-rw-r--r-- | extension/react-app/src/redux/selectors/miscSelectors.ts | 5 | ||||
-rw-r--r-- | extension/react-app/src/redux/slices/chatSlice.ts | 93 | ||||
-rw-r--r-- | extension/react-app/src/redux/slices/configSlice.ts | 45 | ||||
-rw-r--r-- | extension/react-app/src/redux/slices/debugContexSlice.ts | 149 | ||||
-rw-r--r-- | extension/react-app/src/redux/slices/miscSlice.ts | 16 | ||||
-rw-r--r-- | extension/react-app/src/redux/store.ts | 43 |
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; |