Skip to content

Commit 6034366

Browse files
feat: persist session mode (#471)
Co-authored-by: Charles Vien <charles.v@posthog.com>
1 parent a08925f commit 6034366

2 files changed

Lines changed: 86 additions & 2 deletions

File tree

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { create } from "zustand";
2+
import { persist } from "zustand/middleware";
3+
import type { ExecutionMode } from "./sessionStore";
4+
5+
interface SessionModeState {
6+
/** Map of taskId -> last used execution mode */
7+
taskModes: Record<string, ExecutionMode>;
8+
}
9+
10+
interface SessionModeActions {
11+
/** Save the mode for a task */
12+
setTaskMode: (taskId: string, mode: ExecutionMode) => void;
13+
/** Get the saved mode for a task */
14+
getTaskMode: (taskId: string) => ExecutionMode | undefined;
15+
}
16+
17+
type SessionModeStore = SessionModeState & SessionModeActions;
18+
19+
export const useSessionModeStore = create<SessionModeStore>()(
20+
persist(
21+
(set, get) => ({
22+
taskModes: {},
23+
24+
setTaskMode: (taskId, mode) => {
25+
set((state) => ({
26+
taskModes: { ...state.taskModes, [taskId]: mode },
27+
}));
28+
},
29+
30+
getTaskMode: (taskId) => {
31+
return get().taskModes[taskId];
32+
},
33+
}),
34+
{
35+
name: "session-mode-storage",
36+
},
37+
),
38+
);
39+
40+
/** Non-hook accessor for getting task mode */
41+
export function getPersistedTaskMode(
42+
taskId: string,
43+
): ExecutionMode | undefined {
44+
return useSessionModeStore.getState().getTaskMode(taskId);
45+
}
46+
47+
/** Non-hook accessor for setting task mode */
48+
export function setPersistedTaskMode(
49+
taskId: string,
50+
mode: ExecutionMode,
51+
): void {
52+
useSessionModeStore.getState().setTaskMode(taskId, mode);
53+
}

apps/array/src/renderer/features/sessions/stores/sessionStore.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
findPendingPermissions,
2828
type PermissionRequest,
2929
} from "../utils/parseSessionLogs";
30+
import { getPersistedTaskMode, setPersistedTaskMode } from "./sessionModeStore";
3031

3132
const log = logger.scope("session-store");
3233
const CLOUD_POLLING_INTERVAL_MS = 500;
@@ -149,6 +150,7 @@ function subscribeToChannel(taskRunId: string) {
149150
newMode === "acceptEdits"
150151
) {
151152
session.currentMode = newMode;
153+
setPersistedTaskMode(session.taskId, newMode);
152154
log.info("Session mode updated", { taskRunId, newMode });
153155
}
154156
}
@@ -595,10 +597,14 @@ const useStore = create<SessionStore>()(
595597
});
596598
}
597599

600+
const persistedMode = getPersistedTaskMode(taskId);
598601
const session = createBaseSession(taskRunId, taskId, false);
599602
session.events = events;
600603
session.logUrl = logUrl;
601604
session.pendingPermissions = pendingPermissions;
605+
if (persistedMode) {
606+
session.currentMode = persistedMode;
607+
}
602608

603609
addSession(session);
604610
subscribeToChannel(taskRunId);
@@ -616,6 +622,24 @@ const useStore = create<SessionStore>()(
616622

617623
if (result) {
618624
updateSession(taskRunId, { status: "connected" });
625+
if (persistedMode) {
626+
try {
627+
await trpcVanilla.agent.setMode.mutate({
628+
sessionId: taskRunId,
629+
modeId: persistedMode,
630+
});
631+
log.info("Restored persisted mode after reconnect", {
632+
taskId,
633+
taskRunId,
634+
mode: persistedMode,
635+
});
636+
} catch (error) {
637+
log.warn("Failed to restore persisted mode after reconnect", {
638+
taskId,
639+
error,
640+
});
641+
}
642+
}
619643
} else {
620644
unsubscribeFromChannel(taskRunId);
621645
removeSession(taskRunId);
@@ -640,6 +664,9 @@ const useStore = create<SessionStore>()(
640664
return;
641665
}
642666

667+
const persistedMode = getPersistedTaskMode(taskId);
668+
const effectiveMode = executionMode ?? persistedMode;
669+
643670
const { defaultModel, defaultFramework } = useSettingsStore.getState();
644671
const result = await trpcVanilla.agent.start.mutate({
645672
taskId,
@@ -650,19 +677,22 @@ const useStore = create<SessionStore>()(
650677
projectId: auth.projectId,
651678
model: defaultModel,
652679
framework: defaultFramework,
653-
executionMode,
680+
executionMode: effectiveMode,
654681
});
655682

656683
const session = createBaseSession(
657684
taskRun.id,
658685
taskId,
659686
false,
660687
defaultFramework,
661-
executionMode,
688+
effectiveMode === "default" ? undefined : effectiveMode,
662689
);
663690
session.channel = result.channel;
664691
session.status = "connected";
665692
session.model = defaultModel;
693+
if (persistedMode && !executionMode) {
694+
session.currentMode = persistedMode;
695+
}
666696

667697
addSession(session);
668698
subscribeToChannel(taskRun.id);
@@ -903,6 +933,7 @@ const useStore = create<SessionStore>()(
903933
modeId,
904934
});
905935
updateSession(session.taskRunId, { currentMode: modeId });
936+
setPersistedTaskMode(taskId, modeId);
906937
} catch (error) {
907938
log.error("Failed to change session mode", {
908939
taskId,

0 commit comments

Comments
 (0)