|
|
@@ -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<boolean>
|
|
|
+}
|
|
|
+
|
|
|
function createGlobalSync() {
|
|
|
const globalSDK = useGlobalSDK()
|
|
|
const platform = usePlatform()
|
|
|
+ const vcsCache = new Map<string, VcsCache>()
|
|
|
const [globalStore, setGlobalStore] = createStore<{
|
|
|
ready: boolean
|
|
|
error?: InitError
|
|
|
@@ -86,10 +105,16 @@ function createGlobalSync() {
|
|
|
provider_auth: {},
|
|
|
})
|
|
|
|
|
|
- const children: Record<string, ReturnType<typeof createStore<State>>> = {}
|
|
|
+ const children: Record<string, [Store<State>, SetStoreFunction<State>]> = {}
|
|
|
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<State>({
|
|
|
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<string, PermissionRequest[]> = {}
|
|
|
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": {
|