diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx index 29cca133bb..7d58782101 100644 --- a/packages/opencode/src/cli/cmd/tui/app.tsx +++ b/packages/opencode/src/cli/cmd/tui/app.tsx @@ -76,8 +76,6 @@ const appBindingCommands = [ "command.palette.show", "session.list", "session.new", - "session.cycle_recent", - "session.cycle_recent_reverse", "session.quick_switch.1", "session.quick_switch.2", "session.quick_switch.3", @@ -482,35 +480,15 @@ function App(props: { onSnapshot?: () => Promise }) { }, }, ...(Flag.OPENCODE_EXPERIMENTAL_SESSION_SWITCHING - ? [ - { - name: "session.cycle_recent", - title: "Cycle to previous recent session", - category: "Session", - hidden: true, - run: () => { - local.session.cycleRecent(1) - }, + ? Array.from({ length: 9 }, (_, i) => ({ + name: `session.quick_switch.${i + 1}`, + title: `Switch to session in quick slot ${i + 1}`, + category: "Session", + hidden: true, + run: () => { + local.session.quickSwitch(i + 1) }, - { - name: "session.cycle_recent_reverse", - title: "Cycle to next recent session", - category: "Session", - hidden: true, - run: () => { - local.session.cycleRecent(-1) - }, - }, - ...Array.from({ length: 9 }, (_, i) => ({ - name: `session.quick_switch.${i + 1}`, - title: `Switch to session in quick slot ${i + 1}`, - category: "Session", - hidden: true, - run: () => { - local.session.quickSwitch(i + 1) - }, - })), - ] + })) : []), { name: "model.list", @@ -830,9 +808,7 @@ function App(props: { onSnapshot?: () => Promise }) { "app", Flag.OPENCODE_EXPERIMENTAL_SESSION_SWITCHING ? appBindingCommands - : appBindingCommands.filter( - (c) => !c.startsWith("session.cycle_recent") && !c.startsWith("session.quick_switch"), - ), + : appBindingCommands.filter((c) => !c.startsWith("session.quick_switch")), ), })) diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx index 1dd33106de..68c4a1d07f 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx @@ -130,8 +130,6 @@ export function DialogSessionList() { const [browseOrder] = createSignal(orderByRecency(sync.data.session)) - const RECENT_LIMIT = 5 - const options = createMemo(() => { const enabled = Flag.OPENCODE_EXPERIMENTAL_SESSION_SWITCHING const today = new Date().toDateString() @@ -144,18 +142,12 @@ export function DialogSessionList() { const searchResult = searchResults() const displayOrder = searchResult ? orderByRecency(searchResult) : browseOrder() - const dismissed = enabled ? new Set(local.session.dismissedRecent()) : new Set() const pinned = enabled ? local.session.pinned().filter((id) => sessionMap.has(id)) : [] const pinnedSet = new Set(pinned) const slotByID = enabled ? new Map(local.session.slots().map((id, i) => [id, i + 1])) : new Map() - const recent = enabled - ? displayOrder.filter((id) => !pinnedSet.has(id) && !dismissed.has(id)).slice(0, RECENT_LIMIT) - : [] - const recentSet = new Set(recent) - function buildOption(id: string, category: string) { const x = sessionMap.get(id) if (!x) return undefined @@ -198,7 +190,7 @@ export function DialogSessionList() { } const remaining = displayOrder - .filter((id) => !pinnedSet.has(id) && !recentSet.has(id)) + .filter((id) => !pinnedSet.has(id)) .map((id) => { const x = sessionMap.get(id) if (!x) return undefined @@ -209,7 +201,6 @@ export function DialogSessionList() { return [ ...pinned.map((id) => buildOption(id, "Pinned")).filter((x) => x !== undefined), - ...recent.map((id) => buildOption(id, "Recent")).filter((x) => x !== undefined), ...remaining, ] }) @@ -245,21 +236,6 @@ export function DialogSessionList() { local.session.togglePin(option.value) }, }, - { - command: "session.toggle.recent", - title: "toggle recent", - onTrigger: (option: { value: string }) => { - if (local.session.isPinned(option.value)) { - toast.show({ - variant: "info", - message: "Unpin the session first to toggle it in Recent", - duration: 3000, - }) - return - } - local.session.toggleRecent(option.value) - }, - }, ] : []), { diff --git a/packages/opencode/src/cli/cmd/tui/config/keybind.ts b/packages/opencode/src/cli/cmd/tui/config/keybind.ts index 4623893161..bd26cd5d95 100644 --- a/packages/opencode/src/cli/cmd/tui/config/keybind.ts +++ b/packages/opencode/src/cli/cmd/tui/config/keybind.ts @@ -87,9 +87,6 @@ export const Definitions = { session_child_cycle_reverse: keybind("left", "Go to previous child session"), session_parent: keybind("up", "Go to parent session"), session_pin_toggle: keybind("ctrl+f", "Pin or unpin session in the session list"), - session_toggle_recent: keybind("ctrl+h", "Show or hide session in the Recent group"), - session_cycle_recent: keybind("]", "Cycle to the previous recent session"), - session_cycle_recent_reverse: keybind("[", "Cycle to the next recent session"), session_quick_switch_1: keybind("1", "Switch to session in quick slot 1"), session_quick_switch_2: keybind("2", "Switch to session in quick slot 2"), session_quick_switch_3: keybind("3", "Switch to session in quick slot 3"), @@ -273,9 +270,6 @@ export const CommandMap = { session_child_cycle_reverse: "session.child.previous", session_parent: "session.parent", session_pin_toggle: "session.pin.toggle", - session_toggle_recent: "session.toggle.recent", - session_cycle_recent: "session.cycle_recent", - session_cycle_recent_reverse: "session.cycle_recent_reverse", session_quick_switch_1: "session.quick_switch.1", session_quick_switch_2: "session.quick_switch.2", session_quick_switch_3: "session.quick_switch.3", diff --git a/packages/opencode/src/cli/cmd/tui/context/local.tsx b/packages/opencode/src/cli/cmd/tui/context/local.tsx index fc22263151..e33a54b34e 100644 --- a/packages/opencode/src/cli/cmd/tui/context/local.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/local.tsx @@ -1,6 +1,6 @@ import { createStore } from "solid-js/store" import { createSimpleContext } from "./helper" -import { batch, createEffect, createMemo, on } from "solid-js" +import { batch, createEffect, createMemo } from "solid-js" import { useSync } from "@tui/context/sync" import { useTheme } from "@tui/context/theme" import { useRoute } from "@tui/context/route" @@ -8,7 +8,6 @@ import { useEvent } from "@tui/context/event" import { uniqueBy } from "remeda" import path from "path" import { Global } from "@opencode-ai/core/global" -import { Flag } from "@opencode-ai/core/flag/flag" import { iife } from "@/util/iife" import { useToast } from "../ui/toast" import { useArgs } from "./args" @@ -387,13 +386,9 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ const [sessionStore, setSessionStore] = createStore<{ ready: boolean pinned: string[] - dismissedRecent: string[] - recentOrder: string[] }>({ ready: false, pinned: [], - dismissedRecent: [], - recentOrder: [], }) const filePath = path.join(Global.Path.state, "session.json") @@ -409,16 +404,12 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ state.pending = false void Filesystem.writeJson(filePath, { pinned: sessionStore.pinned, - dismissedRecent: sessionStore.dismissedRecent, - recentOrder: sessionStore.recentOrder, }) } Filesystem.readJson(filePath) .then((x: any) => { if (Array.isArray(x.pinned)) setSessionStore("pinned", x.pinned) - if (Array.isArray(x.dismissedRecent)) setSessionStore("dismissedRecent", x.dismissedRecent) - if (Array.isArray(x.recentOrder)) setSessionStore("recentOrder", x.recentOrder) }) .catch(() => {}) .finally(() => { @@ -428,19 +419,10 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ const route = useRoute() const event = useEvent() - let cycling = false const slots = createMemo(() => { - const rootSessions = sync.data.session.filter((x) => x.parentID === undefined) - const existing = new Set(rootSessions.map((x) => x.id)) - const dismissed = new Set(sessionStore.dismissedRecent) - const pins = sessionStore.pinned.filter((id) => existing.has(id)) - const pinnedSet = new Set(pins) - const recent = rootSessions - .filter((x) => !pinnedSet.has(x.id) && !dismissed.has(x.id)) - .toSorted((a, b) => b.time.updated - a.time.updated) - .map((x) => x.id) - return [...pins, ...recent].slice(0, 9) + const existing = new Set(sync.data.session.filter((x) => x.parentID === undefined).map((x) => x.id)) + return sessionStore.pinned.filter((id) => existing.has(id)).slice(0, 9) }) function prune(sessionID: string) { @@ -451,18 +433,6 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ sessionStore.pinned.filter((x) => x !== sessionID), ) } - if (sessionStore.dismissedRecent.includes(sessionID)) { - setSessionStore( - "dismissedRecent", - sessionStore.dismissedRecent.filter((x) => x !== sessionID), - ) - } - if (sessionStore.recentOrder.includes(sessionID)) { - setSessionStore( - "recentOrder", - sessionStore.recentOrder.filter((x) => x !== sessionID), - ) - } save() }) } @@ -471,25 +441,6 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ prune(evt.properties.info.id) }) - if (Flag.OPENCODE_EXPERIMENTAL_SESSION_SWITCHING) { - createEffect( - on( - () => (sessionStore.ready && route.data.type === "session" ? route.data.sessionID : undefined), - (sessionID) => { - if (!sessionID) return - if (cycling) { - cycling = false - return - } - const filtered = sessionStore.recentOrder.filter((x) => x !== sessionID) - const next = [sessionID, ...filtered].slice(0, 20) - setSessionStore("recentOrder", next) - save() - }, - ), - ) - } - return { get ready() { return sessionStore.ready @@ -497,19 +448,10 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ pinned() { return sessionStore.pinned }, - dismissedRecent() { - return sessionStore.dismissedRecent - }, - recentOrder() { - return sessionStore.recentOrder - }, slots, isPinned(sessionID: string) { return sessionStore.pinned.includes(sessionID) }, - isDismissed(sessionID: string) { - return sessionStore.dismissedRecent.includes(sessionID) - }, togglePin(sessionID: string) { batch(() => { const exists = sessionStore.pinned.includes(sessionID) @@ -520,52 +462,12 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ save() }) }, - toggleRecent(sessionID: string) { - batch(() => { - const exists = sessionStore.dismissedRecent.includes(sessionID) - const next = exists - ? sessionStore.dismissedRecent.filter((x) => x !== sessionID) - : [sessionID, ...sessionStore.dismissedRecent] - setSessionStore("dismissedRecent", next) - save() - }) - }, quickSwitch(slot: number) { const target = slots()[slot - 1] if (!target) return if (route.data.type === "session" && route.data.sessionID === target) return route.navigate({ type: "session", sessionID: target }) }, - cycleRecent(direction: 1 | -1) { - if (route.data.type !== "session") { - toast.show({ - variant: "info", - message: "Open a session first to cycle between recent sessions", - duration: 3000, - }) - return - } - const current = route.data.sessionID - const order = sessionStore.recentOrder.filter((id) => - sync.data.session.some((s) => s.id === id && s.parentID === undefined), - ) - if (order.length < 2) { - toast.show({ - variant: "info", - message: "No other recent sessions to cycle to", - duration: 3000, - }) - return - } - const index = order.indexOf(current) - if (index === -1) return - const next = index + direction - if (next < 0 || next >= order.length) return - const target = order[next] - if (!target || target === current) return - cycling = true - route.navigate({ type: "session", sessionID: target }) - }, } }) diff --git a/packages/opencode/src/cli/cmd/tui/feature-plugins/home/tips-view.tsx b/packages/opencode/src/cli/cmd/tui/feature-plugins/home/tips-view.tsx index 8c50914df3..f2a5f97f1e 100644 --- a/packages/opencode/src/cli/cmd/tui/feature-plugins/home/tips-view.tsx +++ b/packages/opencode/src/cli/cmd/tui/feature-plugins/home/tips-view.tsx @@ -29,8 +29,6 @@ type Shortcuts = { messagesToggleConceal: TipShortcut modelCycleRecent: TipShortcut modelList: TipShortcut - sessionCycleRecent: TipShortcut - sessionCycleRecentReverse: TipShortcut sessionExport: TipShortcut sessionInterrupt: TipShortcut sessionList: TipShortcut @@ -41,7 +39,6 @@ type Shortcuts = { sessionQuickSwitch9: TipShortcut sessionSidebarToggle: TipShortcut sessionTimeline: TipShortcut - sessionToggleRecent: TipShortcut statusView: TipShortcut terminalSuspend: TipShortcut themeList: TipShortcut @@ -121,8 +118,6 @@ export function Tips(props: { api: TuiPluginApi; connected?: boolean }) { messagesToggleConceal: configShortcut(props.api, "session.toggle.conceal"), modelCycleRecent: useCommandShortcut("model.cycle_recent"), modelList: useCommandShortcut("model.list"), - sessionCycleRecent: useCommandShortcut("session.cycle_recent"), - sessionCycleRecentReverse: useCommandShortcut("session.cycle_recent_reverse"), sessionExport: configShortcut(props.api, "session.export"), sessionInterrupt: configShortcut(props.api, "session.interrupt"), sessionList: useCommandShortcut("session.list"), @@ -133,7 +128,6 @@ export function Tips(props: { api: TuiPluginApi; connected?: boolean }) { sessionQuickSwitch9: useCommandShortcut("session.quick_switch.9"), sessionSidebarToggle: configShortcut(props.api, "session.sidebar.toggle"), sessionTimeline: configShortcut(props.api, "session.timeline"), - sessionToggleRecent: configShortcut(props.api, "session.toggle.recent"), statusView: useCommandShortcut("opencode.status"), terminalSuspend: useCommandShortcut("terminal.suspend"), themeList: useCommandShortcut("theme.switch"), @@ -183,14 +177,8 @@ const TIPS: Tip[] = [ press(shortcuts.sessionPinToggle(), "in the session list to pin a session so it stays at the top"), (shortcuts) => shortcuts.sessionQuickSwitch1() && shortcuts.sessionQuickSwitch9() - ? `Pinned and recent sessions are bound to ${shortcutText(shortcuts.sessionQuickSwitch1())} through ${shortcutText(shortcuts.sessionQuickSwitch9())} for one-press switching` + ? `Pinned sessions are bound to ${shortcutText(shortcuts.sessionQuickSwitch1())} through ${shortcutText(shortcuts.sessionQuickSwitch9())} for one-press switching` : undefined, - (shortcuts) => - shortcuts.sessionCycleRecent() && shortcuts.sessionCycleRecentReverse() - ? `Press ${shortcutText(shortcuts.sessionCycleRecent())} / ${shortcutText(shortcuts.sessionCycleRecentReverse())} to cycle through recently visited sessions` - : undefined, - (shortcuts) => - press(shortcuts.sessionToggleRecent(), "in the session list to show or hide a session in the Recent group"), ] satisfies Tip[]) : []), "Run {highlight}/compact{/highlight} to summarize long sessions near context limits",