|
|
@@ -16,7 +16,7 @@ import { makeEventListener } from "@solid-primitives/event-listener"
|
|
|
import { useLocation, useNavigate, useParams } from "@solidjs/router"
|
|
|
import { useQuery } from "@tanstack/solid-query"
|
|
|
import { useLayout, LocalProject } from "@/context/layout"
|
|
|
-import { useGlobalSync } from "@/context/global-sync"
|
|
|
+import { useServerSync } from "@/context/server-sync"
|
|
|
import { Persist, persisted } from "@/utils/persist"
|
|
|
import { base64Encode } from "@opencode-ai/core/util/encode"
|
|
|
import { decode64 } from "@/utils/base64"
|
|
|
@@ -35,7 +35,7 @@ import { DragDropProvider, DragDropSensors, DragOverlay, SortableProvider, close
|
|
|
import type { DragEvent } from "@thisbeyond/solid-dnd"
|
|
|
import { useProviders } from "@/hooks/use-providers"
|
|
|
import { showToast, Toast, toaster } from "@opencode-ai/ui/toast"
|
|
|
-import { useGlobalSDK } from "@/context/global-sdk"
|
|
|
+import { useServerSDK } from "@/context/server-sdk"
|
|
|
import { clearWorkspaceTerminals, getTerminalServerScope } from "@/context/terminal"
|
|
|
import { dropSessionCaches, pickSessionCacheEvictions } from "@/context/global-sync/session-cache"
|
|
|
import {
|
|
|
@@ -113,8 +113,8 @@ export default function Layout(props: ParentProps) {
|
|
|
let dialogDead = false
|
|
|
|
|
|
const params = useParams()
|
|
|
- const globalSDK = useGlobalSDK()
|
|
|
- const globalSync = useGlobalSync()
|
|
|
+ const serverSDK = useServerSDK()
|
|
|
+ const serverSync = useServerSync()
|
|
|
const layout = useLayout()
|
|
|
const layoutReady = createMemo(() => layout.ready())
|
|
|
const platform = usePlatform()
|
|
|
@@ -136,7 +136,7 @@ export default function Layout(props: ParentProps) {
|
|
|
if (!slug) return { slug, dir: "" }
|
|
|
const dir = decode64(slug)
|
|
|
if (!dir) return { slug, dir: "" }
|
|
|
- const store = globalSync.peek(dir, { bootstrap: false })
|
|
|
+ const store = serverSync.peek(dir, { bootstrap: false })
|
|
|
return {
|
|
|
slug,
|
|
|
store,
|
|
|
@@ -226,7 +226,7 @@ export default function Layout(props: ParentProps) {
|
|
|
active: () => state.hoverProject,
|
|
|
el: () => state.nav?.querySelector<HTMLElement>("[data-component='sidebar-rail']") ?? state.nav,
|
|
|
onActivate: (directory) => {
|
|
|
- globalSync.child(directory)
|
|
|
+ serverSync.child(directory)
|
|
|
setState("hoverProject", directory)
|
|
|
},
|
|
|
})
|
|
|
@@ -410,7 +410,7 @@ export default function Layout(props: ParentProps) {
|
|
|
alertedAtBySession.delete(sessionKey)
|
|
|
}
|
|
|
|
|
|
- const unsub = globalSDK.event.listen((e) => {
|
|
|
+ const unsub = serverSDK.event.listen((e) => {
|
|
|
if (e.details?.type === "worktree.ready") {
|
|
|
setBusy(e.name, false)
|
|
|
WorktreeState.ready(e.name)
|
|
|
@@ -444,7 +444,7 @@ export default function Layout(props: ParentProps) {
|
|
|
const props = e.details.properties
|
|
|
if (e.details.type === "permission.asked" && permission.autoResponds(e.details.properties, directory)) return
|
|
|
|
|
|
- const [store] = globalSync.child(directory, { bootstrap: false })
|
|
|
+ const [store] = serverSync.child(directory, { bootstrap: false })
|
|
|
const session = store.session.find((s) => s.id === props.sessionID)
|
|
|
const sessionKey = `${directory}:${props.sessionID}`
|
|
|
|
|
|
@@ -507,7 +507,7 @@ export default function Layout(props: ParentProps) {
|
|
|
if (!currentDir() || !currentSession) return
|
|
|
const sessionKey = `${currentDir()}:${currentSession}`
|
|
|
dismissSessionAlert(sessionKey)
|
|
|
- const [store] = globalSync.child(currentDir(), { bootstrap: false })
|
|
|
+ const [store] = serverSync.child(currentDir(), { bootstrap: false })
|
|
|
const childSessions = store.session.filter((s) => s.parentID === currentSession)
|
|
|
for (const child of childSessions) {
|
|
|
dismissSessionAlert(`${currentDir()}:${child.id}`)
|
|
|
@@ -545,11 +545,11 @@ export default function Layout(props: ParentProps) {
|
|
|
const direct = projects.find((p) => pathKey(p.worktree) === key)
|
|
|
if (direct) return direct
|
|
|
|
|
|
- const [child] = globalSync.child(directory, { bootstrap: false })
|
|
|
+ const [child] = serverSync.child(directory, { bootstrap: false })
|
|
|
const id = child.project
|
|
|
if (!id) return
|
|
|
|
|
|
- const meta = globalSync.data.project.find((p) => p.id === id)
|
|
|
+ const meta = serverSync.data.project.find((p) => p.id === id)
|
|
|
const root = meta?.worktree
|
|
|
if (!root) return
|
|
|
|
|
|
@@ -640,7 +640,7 @@ export default function Layout(props: ParentProps) {
|
|
|
|
|
|
const result: Session[] = []
|
|
|
for (const dir of dirs) {
|
|
|
- const [dirStore] = globalSync.child(dir, { bootstrap: true })
|
|
|
+ const [dirStore] = serverSync.child(dir, { bootstrap: true })
|
|
|
const dirSessions = sortedRootSessions(dirStore, now)
|
|
|
result.push(...dirSessions)
|
|
|
}
|
|
|
@@ -692,7 +692,7 @@ export default function Layout(props: ParentProps) {
|
|
|
|
|
|
createEffect(() => {
|
|
|
route()
|
|
|
- globalSDK.url
|
|
|
+ serverSDK.url
|
|
|
|
|
|
prefetchToken.value += 1
|
|
|
clearSessionPrefetchInflight()
|
|
|
@@ -739,13 +739,13 @@ export default function Layout(props: ParentProps) {
|
|
|
}
|
|
|
|
|
|
async function prefetchMessages(directory: string, sessionID: string, token: number) {
|
|
|
- const [store, setStore] = globalSync.child(directory, { bootstrap: false })
|
|
|
+ const [store, setStore] = serverSync.child(directory, { bootstrap: false })
|
|
|
|
|
|
return runSessionPrefetch({
|
|
|
directory,
|
|
|
sessionID,
|
|
|
task: (rev) =>
|
|
|
- retry(() => globalSDK.client.session.messages({ directory, sessionID, limit: prefetchChunk }))
|
|
|
+ retry(() => serverSDK.client.session.messages({ directory, sessionID, limit: prefetchChunk }))
|
|
|
.then((messages) => {
|
|
|
if (prefetchToken.value !== token) return
|
|
|
if (!isSessionPrefetchCurrent(directory, sessionID, rev)) return
|
|
|
@@ -765,7 +765,7 @@ export default function Layout(props: ParentProps) {
|
|
|
if (stale.length > 0) {
|
|
|
clearSessionPrefetch(directory, stale)
|
|
|
for (const id of stale) {
|
|
|
- globalSync.todo.set(id, undefined)
|
|
|
+ serverSync.todo.set(id, undefined)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -830,7 +830,7 @@ export default function Layout(props: ParentProps) {
|
|
|
const directory = session.directory
|
|
|
if (!directory) return
|
|
|
|
|
|
- const [store] = globalSync.child(directory, { bootstrap: false })
|
|
|
+ const [store] = serverSync.child(directory, { bootstrap: false })
|
|
|
const cached = untrack(() => {
|
|
|
const info = getSessionPrefetch(directory, session.id)
|
|
|
return shouldSkipSessionPrefetch({
|
|
|
@@ -935,7 +935,7 @@ export default function Layout(props: ParentProps) {
|
|
|
if (!target) return
|
|
|
|
|
|
// warm up child store to prevent flicker
|
|
|
- globalSync.child(target.worktree)
|
|
|
+ serverSync.child(target.worktree)
|
|
|
void openProject(target.worktree)
|
|
|
}
|
|
|
|
|
|
@@ -944,7 +944,7 @@ export default function Layout(props: ParentProps) {
|
|
|
const target = projects[index]
|
|
|
if (!target) return
|
|
|
|
|
|
- globalSync.child(target.worktree)
|
|
|
+ serverSync.child(target.worktree)
|
|
|
void openProject(target.worktree)
|
|
|
}
|
|
|
|
|
|
@@ -973,12 +973,12 @@ export default function Layout(props: ParentProps) {
|
|
|
}
|
|
|
|
|
|
async function archiveSession(session: Session) {
|
|
|
- const [store, setStore] = globalSync.child(session.directory)
|
|
|
+ const [store, setStore] = serverSync.child(session.directory)
|
|
|
const sessions = store.session ?? []
|
|
|
const index = sessions.findIndex((s) => s.id === session.id)
|
|
|
const nextSession = sessions[index + 1] ?? sessions[index - 1]
|
|
|
|
|
|
- await globalSDK.client.session.update({
|
|
|
+ await serverSDK.client.session.update({
|
|
|
directory: session.directory,
|
|
|
sessionID: session.id,
|
|
|
time: { archived: Date.now() },
|
|
|
@@ -1246,11 +1246,11 @@ export default function Layout(props: ParentProps) {
|
|
|
)
|
|
|
if (known) return known[0]
|
|
|
|
|
|
- const [child] = globalSync.child(directory, { bootstrap: false })
|
|
|
+ const [child] = serverSync.child(directory, { bootstrap: false })
|
|
|
const id = child.project
|
|
|
if (!id) return directory
|
|
|
|
|
|
- const meta = globalSync.data.project.find((item) => item.id === id)
|
|
|
+ const meta = serverSync.data.project.find((item) => item.id === id)
|
|
|
return meta?.worktree ?? directory
|
|
|
}
|
|
|
|
|
|
@@ -1298,7 +1298,7 @@ export default function Layout(props: ParentProps) {
|
|
|
}
|
|
|
const refreshDirs = async (target?: string) => {
|
|
|
if (!target || target === root || canOpen(target)) return canOpen(target)
|
|
|
- const listed = await globalSDK.client.worktree
|
|
|
+ const listed = await serverSDK.client.worktree
|
|
|
.list({ directory: root })
|
|
|
.then((x) => x.data ?? [])
|
|
|
.catch(() => [] as string[])
|
|
|
@@ -1307,13 +1307,13 @@ export default function Layout(props: ParentProps) {
|
|
|
}
|
|
|
const openSession = async (target: { directory: string; id: string }) => {
|
|
|
if (!canOpen(target.directory)) return false
|
|
|
- const [data] = globalSync.child(target.directory, { bootstrap: false })
|
|
|
+ const [data] = serverSync.child(target.directory, { bootstrap: false })
|
|
|
if (data.session.some((item) => item.id === target.id)) {
|
|
|
setStore("lastProjectSession", root, { directory: target.directory, id: target.id, at: Date.now() })
|
|
|
navigateWithSidebarReset(`/${base64Encode(target.directory)}/session/${target.id}`)
|
|
|
return true
|
|
|
}
|
|
|
- const resolved = await globalSDK.client.session
|
|
|
+ const resolved = await serverSDK.client.session
|
|
|
.get({ sessionID: target.id })
|
|
|
.then((x) => x.data)
|
|
|
.catch(() => undefined)
|
|
|
@@ -1333,7 +1333,7 @@ export default function Layout(props: ParentProps) {
|
|
|
}
|
|
|
|
|
|
const latest = latestRootSession(
|
|
|
- dirs.map((item) => globalSync.child(item, { bootstrap: false })[0]),
|
|
|
+ dirs.map((item) => serverSync.child(item, { bootstrap: false })[0]),
|
|
|
Date.now(),
|
|
|
)
|
|
|
if (latest && (await openSession(latest))) {
|
|
|
@@ -1344,7 +1344,7 @@ export default function Layout(props: ParentProps) {
|
|
|
await Promise.all(
|
|
|
dirs.map(async (item) => ({
|
|
|
path: { directory: item },
|
|
|
- session: await globalSDK.client.session
|
|
|
+ session: await serverSDK.client.session
|
|
|
.list({ directory: item })
|
|
|
.then((x) => x.data ?? [])
|
|
|
.catch(() => []),
|
|
|
@@ -1405,11 +1405,11 @@ export default function Layout(props: ParentProps) {
|
|
|
const name = next === getFilename(project.worktree) ? "" : next
|
|
|
|
|
|
if (project.id && project.id !== "global") {
|
|
|
- await globalSDK.client.project.update({ projectID: project.id, directory: project.worktree, name })
|
|
|
+ await serverSDK.client.project.update({ projectID: project.id, directory: project.worktree, name })
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- globalSync.project.meta(project.worktree, { name })
|
|
|
+ serverSync.project.meta(project.worktree, { name })
|
|
|
}
|
|
|
|
|
|
const renameWorkspace = (directory: string, next: string, projectId?: string, branch?: string) => {
|
|
|
@@ -1506,7 +1506,7 @@ export default function Layout(props: ParentProps) {
|
|
|
|
|
|
setBusy(directory, true)
|
|
|
|
|
|
- const result = await globalSDK.client.worktree
|
|
|
+ const result = await serverSDK.client.worktree
|
|
|
.remove({ directory: root, worktreeRemoveInput: { directory } })
|
|
|
.then((x) => x.data)
|
|
|
.catch((err) => {
|
|
|
@@ -1525,7 +1525,7 @@ export default function Layout(props: ParentProps) {
|
|
|
clearLastProjectSession(root)
|
|
|
}
|
|
|
|
|
|
- globalSync.set(
|
|
|
+ serverSync.set(
|
|
|
"project",
|
|
|
produce((draft) => {
|
|
|
const project = draft.find((item) => item.worktree === root)
|
|
|
@@ -1564,7 +1564,7 @@ export default function Layout(props: ParentProps) {
|
|
|
})
|
|
|
const dismiss = () => toaster.dismiss(progress)
|
|
|
|
|
|
- const sessions: Session[] = await globalSDK.client.session
|
|
|
+ const sessions: Session[] = await serverSDK.client.session
|
|
|
.list({ directory })
|
|
|
.then((x) => x.data ?? [])
|
|
|
.catch(() => [])
|
|
|
@@ -1575,9 +1575,9 @@ export default function Layout(props: ParentProps) {
|
|
|
platform,
|
|
|
getTerminalServerScope(server.current, server.key),
|
|
|
)
|
|
|
- await globalSDK.client.instance.dispose({ directory }).catch(() => undefined)
|
|
|
+ await serverSDK.client.instance.dispose({ directory }).catch(() => undefined)
|
|
|
|
|
|
- const result = await globalSDK.client.worktree
|
|
|
+ const result = await serverSDK.client.worktree
|
|
|
.reset({ directory: root, worktreeResetInput: { directory } })
|
|
|
.then((x) => x.data)
|
|
|
.catch((err) => {
|
|
|
@@ -1599,7 +1599,7 @@ export default function Layout(props: ParentProps) {
|
|
|
sessions
|
|
|
.filter((session) => session.time.archived === undefined)
|
|
|
.map((session) =>
|
|
|
- globalSDK.client.session
|
|
|
+ serverSDK.client.session
|
|
|
.update({
|
|
|
sessionID: session.id,
|
|
|
directory: session.directory,
|
|
|
@@ -1640,7 +1640,7 @@ export default function Layout(props: ParentProps) {
|
|
|
})
|
|
|
|
|
|
onMount(() => {
|
|
|
- globalSDK.client.file
|
|
|
+ serverSDK.client.file
|
|
|
.status({ directory: props.directory })
|
|
|
.then((x) => {
|
|
|
const files = x.data ?? []
|
|
|
@@ -1699,7 +1699,7 @@ export default function Layout(props: ParentProps) {
|
|
|
})
|
|
|
|
|
|
const refresh = async () => {
|
|
|
- const sessions = await globalSDK.client.session
|
|
|
+ const sessions = await serverSDK.client.session
|
|
|
.list({ directory: props.directory })
|
|
|
.then((x) => x.data ?? [])
|
|
|
.catch(() => [])
|
|
|
@@ -1708,7 +1708,7 @@ export default function Layout(props: ParentProps) {
|
|
|
}
|
|
|
|
|
|
onMount(() => {
|
|
|
- globalSDK.client.file
|
|
|
+ serverSDK.client.file
|
|
|
.status({ directory: props.directory })
|
|
|
.then((x) => {
|
|
|
const files = x.data ?? []
|
|
|
@@ -1842,7 +1842,7 @@ export default function Layout(props: ParentProps) {
|
|
|
const next = new Set(dirs)
|
|
|
for (const directory of next) {
|
|
|
if (loadedSessionDirs.has(directory)) continue
|
|
|
- void globalSync.project.loadSessions(directory)
|
|
|
+ void serverSync.project.loadSessions(directory)
|
|
|
}
|
|
|
|
|
|
loadedSessionDirs.clear()
|
|
|
@@ -1939,7 +1939,7 @@ export default function Layout(props: ParentProps) {
|
|
|
|
|
|
const createWorkspace = async (project: LocalProject) => {
|
|
|
clearSidebarHoverState()
|
|
|
- const created = await globalSDK.client.worktree
|
|
|
+ const created = await serverSDK.client.worktree
|
|
|
.create({ directory: project.worktree })
|
|
|
.then((x) => x.data)
|
|
|
.catch((err) => {
|
|
|
@@ -1973,7 +1973,7 @@ export default function Layout(props: ParentProps) {
|
|
|
return [created.directory, ...next]
|
|
|
})
|
|
|
|
|
|
- globalSync.child(created.directory)
|
|
|
+ serverSync.child(created.directory)
|
|
|
navigateWithSidebarReset(`/${base64Encode(created.directory)}/session`)
|
|
|
}
|
|
|
|
|
|
@@ -2078,7 +2078,7 @@ export default function Layout(props: ParentProps) {
|
|
|
if (!item) return false
|
|
|
return item.vcs === "git" || layout.sidebar.workspaces(item.worktree)()
|
|
|
})
|
|
|
- const homedir = createMemo(() => globalSync.data.path.home)
|
|
|
+ const homedir = createMemo(() => serverSync.data.path.home)
|
|
|
|
|
|
return (
|
|
|
<div
|