From 47d43aaf2db7ecb0c6cd5a406efa6a43db656596 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Thu, 15 Jan 2026 14:46:26 -0600 Subject: [PATCH] feat(app): persist workspace branch --- packages/app/src/context/global-sync.tsx | 57 +++++++++++++++++++++--- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/packages/app/src/context/global-sync.tsx b/packages/app/src/context/global-sync.tsx index a0b257056..94c39d2f0 100644 --- a/packages/app/src/context/global-sync.tsx +++ b/packages/app/src/context/global-sync.tsx @@ -19,15 +19,27 @@ import { type QuestionRequest, createOpencodeClient, } from "@opencode-ai/sdk/v2/client" -import { createStore, produce, reconcile } from "solid-js/store" +import { createStore, produce, reconcile, type SetStoreFunction, type Store } from "solid-js/store" import { Binary } from "@opencode-ai/util/binary" import { retry } from "@opencode-ai/util/retry" import { useGlobalSDK } from "./global-sdk" import { ErrorPage, type InitError } from "../pages/error" -import { batch, createContext, useContext, onCleanup, onMount, type ParentProps, Switch, Match } from "solid-js" +import { + batch, + createContext, + createEffect, + useContext, + onCleanup, + onMount, + type Accessor, + type ParentProps, + Switch, + Match, +} from "solid-js" import { showToast } from "@opencode-ai/ui/toast" import { getFilename } from "@opencode-ai/util/path" import { usePlatform } from "./platform" +import { Persist, persisted } from "@/utils/persist" type State = { status: "loading" | "partial" | "complete" @@ -68,9 +80,16 @@ type State = { } } +type VcsCache = { + store: Store<{ value: VcsInfo | undefined }> + setStore: SetStoreFunction<{ value: VcsInfo | undefined }> + ready: Accessor +} + function createGlobalSync() { const globalSDK = useGlobalSDK() const platform = usePlatform() + const vcsCache = new Map() const [globalStore, setGlobalStore] = createStore<{ ready: boolean error?: InitError @@ -86,10 +105,16 @@ function createGlobalSync() { provider_auth: {}, }) - const children: Record>> = {} + const children: Record, SetStoreFunction]> = {} function child(directory: string) { if (!directory) console.error("No directory provided") if (!children[directory]) { + const cache = persisted( + Persist.workspace(directory, "vcs", ["vcs.v1"]), + createStore({ value: undefined as VcsInfo | undefined }), + ) + vcsCache.set(directory, { store: cache[0], setStore: cache[1], ready: cache[3] }) + children[directory] = createStore({ project: "", provider: { all: [], connected: [], default: {} }, @@ -107,14 +132,16 @@ function createGlobalSync() { question: {}, mcp: {}, lsp: [], - vcs: undefined, + vcs: cache[0].value, limit: 5, message: {}, part: {}, }) bootstrapInstance(directory) } - return children[directory] + const childStore = children[directory] + if (!childStore) throw new Error("Failed to create store") + return childStore } async function loadSessions(directory: string) { @@ -157,6 +184,8 @@ function createGlobalSync() { async function bootstrapInstance(directory: string) { if (!directory) return const [store, setStore] = child(directory) + const cache = vcsCache.get(directory) + if (!cache) return const sdk = createOpencodeClient({ baseUrl: globalSDK.url, fetch: platform.fetch, @@ -164,6 +193,13 @@ function createGlobalSync() { throwOnError: true, }) + createEffect(() => { + if (!cache.ready()) return + const cached = cache.store.value + if (!cached?.branch) return + setStore("vcs", (value) => value ?? cached) + }) + const blockingRequests = { project: () => sdk.project.current().then((x) => setStore("project", x.data!.id)), provider: () => @@ -193,7 +229,11 @@ function createGlobalSync() { loadSessions(directory), sdk.mcp.status().then((x) => setStore("mcp", x.data!)), sdk.lsp.status().then((x) => setStore("lsp", x.data!)), - sdk.vcs.get().then((x) => setStore("vcs", x.data)), + sdk.vcs.get().then((x) => { + const next = x.data ?? store.vcs + setStore("vcs", next) + if (next?.branch) cache.setStore("value", next) + }), sdk.permission.list().then((x) => { const grouped: Record = {} for (const perm of x.data ?? []) { @@ -406,7 +446,10 @@ function createGlobalSync() { break } case "vcs.branch.updated": { - setStore("vcs", { branch: event.properties.branch }) + const next = { branch: event.properties.branch } + setStore("vcs", next) + const cache = vcsCache.get(directory) + if (cache) cache.setStore("value", next) break } case "permission.asked": {