Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion gui/src/hooks/ParallelListeners.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ import { setTTSActive } from "../redux/slices/uiSlice";
import { modelSupportsReasoning } from "core/llm/autodetect";
import { cancelStream } from "../redux/thunks/cancelStream";
import { handleApplyStateUpdate } from "../redux/thunks/handleApplyStateUpdate";
import { refreshSessionMetadata } from "../redux/thunks/session";
import {
loadLastSession,
refreshSessionMetadata,
} from "../redux/thunks/session";
import { updateFileSymbolsFromHistory } from "../redux/thunks/updateFileSymbols";
import {
setDocumentStylesFromLocalStorage,
Expand Down Expand Up @@ -240,6 +243,10 @@ function ParallelListeners() {
migrateLocalStorage(dispatch);
}, []);

useEffect(() => {
void dispatch(loadLastSession());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is pretty critical loading could we add some retry logic and error handling? Maybe retry with exponential backoff or a few times or similar

}, []);

return <></>;
}

Expand Down
10 changes: 3 additions & 7 deletions gui/src/pages/gui/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ import { streamResponseThunk } from "../../redux/thunks/streamResponse";
import { isJetBrains, isMetaEquivalentKeyPressed } from "../../util";
import { ToolCallDiv } from "./ToolCallDiv";

import { useStore } from "react-redux";
import { FatalErrorIndicator } from "../../components/config/FatalErrorNotice";
import InlineErrorMessage from "../../components/mainInput/InlineErrorMessage";
import { RootState } from "../../redux/store";
import { cancelStream } from "../../redux/thunks/cancelStream";
import { EmptyChatBody } from "./EmptyChatBody";
import { ExploreDialogWatcher } from "./ExploreDialogWatcher";
import { useAutoScroll } from "./useAutoScroll";
import { useStore } from "react-redux";
import { RootState } from "../../redux/store";

// Helper function to find the index of the latest conversation summary
function findLatestSummaryIndex(history: ChatHistoryItem[]): number {
Expand Down Expand Up @@ -431,11 +431,7 @@ export function Chat() {
{history.length === 0 && lastSessionId && !isInEdit && (
<NewSessionButton
onClick={async () => {
await dispatch(
loadLastSession({
saveCurrentSession: true,
}),
);
await dispatch(loadLastSession());
}}
className="flex items-center gap-2"
>
Expand Down
11 changes: 0 additions & 11 deletions gui/src/redux/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
ThunkDispatch,
UnknownAction,
} from "@reduxjs/toolkit";
import { createLogger } from "redux-logger";
import {
createMigrate,
MigrationManifest,
Expand Down Expand Up @@ -35,9 +34,7 @@ const rootReducer = combineReducers({

const saveSubsetFilters = [
createFilter("session", [
"history",
"id",
"lastSessionId",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We still need to persist lastSessionId

"title",

// Persist edit mode in case closes in middle
Expand Down Expand Up @@ -73,7 +70,6 @@ const migrations: MigrationManifest = {
defaultModelTitle: oldState?.state?.defaultModelTitle ?? undefined,
},
session: {
history: oldState?.state?.history ?? [],
id: oldState?.state?.sessionId ?? "",
},
tabs: {
Expand Down Expand Up @@ -108,13 +104,6 @@ const persistedReducer = persistReducer<ReturnType<typeof rootReducer>>(
export function setupStore(options: { ideMessenger?: IIdeMessenger }) {
const ideMessenger = options.ideMessenger ?? new IdeMessenger();

const logger = createLogger({
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be used if you uncomment the .concat(logger) below. For debugging

// Customize logger options if needed
collapsed: true, // Collapse console groups by default
timestamp: false, // Remove timestamps from log
diff: true, // Show diff between states
});

return configureStore({
// persistedReducer causes type errors with async thunks
reducer: persistedReducer as unknown as typeof rootReducer,
Expand Down
6 changes: 1 addition & 5 deletions gui/src/redux/thunks/edit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,7 @@ export const exitEdit = createAsyncThunk<
if (openNewSession || state.editModeState.lastNonEditSessionWasEmpty) {
dispatch(newSession());
} else {
await dispatch(
loadLastSession({
saveCurrentSession: false,
}),
);
await dispatch(loadLastSession());
}

dispatch(setMode(state.editModeState.returnToMode));
Expand Down
29 changes: 11 additions & 18 deletions gui/src/redux/thunks/session.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createAsyncThunk, unwrapResult } from "@reduxjs/toolkit";
import { ChatMessage, Session, BaseSessionMetadata } from "core";
import { BaseSessionMetadata, ChatMessage, Session } from "core";
import { RemoteSessionMetadata } from "core/control-plane/client";
import { NEW_SESSION_TITLE } from "core/util/constants";
import { renderChatMessage } from "core/util/messageContent";
Expand Down Expand Up @@ -67,11 +67,7 @@ export const deleteSession = createAsyncThunk<void, string, ThunkApiType>(
dispatch(deleteSessionMetadata(id)); // optimistic
const state = getState();
if (id === state.session.id) {
await dispatch(
loadLastSession({
saveCurrentSession: false,
}),
);
await dispatch(loadLastSession());
}
const result = await extra.ideMessenger.request("history/delete", { id });
if (result.status === "error") {
Expand Down Expand Up @@ -146,20 +142,17 @@ export const loadRemoteSession = createAsyncThunk<
},
);

export const loadLastSession = createAsyncThunk<
void,
{
saveCurrentSession: boolean;
},
ThunkApiType
>(
export const loadLastSession = createAsyncThunk<void, void, ThunkApiType>(
"session/loadLast",
async ({ saveCurrentSession }, { extra, dispatch, getState }) => {
const state = getState();

if (state.session.id && saveCurrentSession) {
async (_, { extra, dispatch, getState }) => {
let lastSessionId = getState().session.lastSessionId;

const lastSessionResult = await extra.ideMessenger.request("history/list", {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just used persisted lastSessionId still rather than listing history. If there's noLast sessionId we start a new session

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That being said might just comment it out since we will want some version of this soon for per-workspace sessions!

limit: 1,
});
if (lastSessionResult.status === "success") {
lastSessionId = lastSessionResult.content.at(0)?.sessionId;
}
const lastSessionId = getState().session.lastSessionId;

if (!lastSessionId) {
dispatch(newSession());
Expand Down
Loading