From 8fe0425c751226839abff7ce5ccdd9e468d05eaf Mon Sep 17 00:00:00 2001 From: dbpolito Date: Mon, 19 Jan 2026 18:43:08 -0300 Subject: [PATCH 1/5] Desktop: New Worskpace Improvements --- packages/app/src/context/global-sync.tsx | 14 +++++++++++--- packages/app/src/pages/layout.tsx | 11 ++++++++--- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/packages/app/src/context/global-sync.tsx b/packages/app/src/context/global-sync.tsx index 96f8c63eab2..4671bed48b6 100644 --- a/packages/app/src/context/global-sync.tsx +++ b/packages/app/src/context/global-sync.tsx @@ -74,6 +74,7 @@ type State = { lsp: LspStatus[] vcs: VcsInfo | undefined limit: number + new?: boolean message: { [sessionID: string]: Message[] } @@ -110,8 +111,9 @@ function createGlobalSync() { }) const children: Record, SetStoreFunction]> = {} + const bootstrapPromises: Record> = {} - function child(directory: string) { + function child(directory: string, options?: { new?: boolean }) { if (!directory) console.error("No directory provided") if (!children[directory]) { const cache = runWithOwner(owner, () => @@ -145,8 +147,9 @@ function createGlobalSync() { limit: 5, message: {}, part: {}, + new: options?.new, }) - bootstrapInstance(directory) + bootstrapPromises[directory] = bootstrapInstance(directory) } runWithOwner(owner, init) @@ -156,6 +159,10 @@ function createGlobalSync() { return childStore } + function wait(directory: string) { + return bootstrapPromises[directory] ?? Promise.resolve() + } + async function loadSessions(directory: string) { const [store, setStore] = child(directory) const limit = store.limit @@ -348,7 +355,7 @@ function createGlobalSync() { const [store, setStore] = child(directory) switch (event.type) { case "server.instance.disposed": { - bootstrapInstance(directory) + bootstrapPromises[directory] = bootstrapInstance(directory) break } case "session.created": { @@ -638,6 +645,7 @@ function createGlobalSync() { return globalStore.error }, child, + wait, bootstrap, project: { loadSessions, diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx index 9daac949e43..f980ab91b19 100644 --- a/packages/app/src/pages/layout.tsx +++ b/packages/app/src/pages/layout.tsx @@ -1521,7 +1521,9 @@ export default function Layout(props: ParentProps) { return workspaceName(props.directory) ?? name }) const open = createMemo(() => store.workspaceExpanded[props.directory] ?? true) - const loading = createMemo(() => open() && workspaceStore.status !== "complete" && sessions().length === 0) + const loading = createMemo( + () => open() && !workspaceStore.new && workspaceStore.status !== "complete" && sessions().length === 0, + ) const hasMore = createMemo(() => local() && workspaceStore.sessionTotal > workspaceStore.session.length) const loadMore = async () => { if (!local()) return @@ -1804,7 +1806,9 @@ export default function Layout(props: ParentProps) { .filter((session) => !session.parentID && !session.time?.archived) .toSorted(sortSessions), ) - const loading = createMemo(() => workspaceStore.status !== "complete" && sessions().length === 0) + const loading = createMemo( + () => !workspaceStore.new && workspaceStore.status !== "complete" && sessions().length === 0, + ) const hasMore = createMemo(() => workspaceStore.sessionTotal > workspaceStore.session.length) const loadMore = async () => { setWorkspaceStore("limit", (limit) => limit + 5) @@ -1876,7 +1880,8 @@ export default function Layout(props: ParentProps) { if (!created?.directory) return - globalSync.child(created.directory) + globalSync.child(created.directory, { new: true }) + await globalSync.wait(created.directory) navigate(`/${base64Encode(created.directory)}/session`) } From 7f4a7789791f5cd15549b2a5e7b3f073dd003d82 Mon Sep 17 00:00:00 2001 From: dbpolito Date: Mon, 19 Jan 2026 18:44:40 -0300 Subject: [PATCH 2/5] Tweak --- packages/app/src/context/global-sync.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/app/src/context/global-sync.tsx b/packages/app/src/context/global-sync.tsx index 4671bed48b6..c1ffea78ede 100644 --- a/packages/app/src/context/global-sync.tsx +++ b/packages/app/src/context/global-sync.tsx @@ -319,6 +319,7 @@ function createGlobalSync() { }), ]).then(() => { setStore("status", "complete") + setStore("new", false) }) }) .catch((e) => setGlobalStore("error", e)) From 6f8ddf5fb9eadbd596e06e47d559c984f188e65e Mon Sep 17 00:00:00 2001 From: dbpolito Date: Mon, 19 Jan 2026 19:13:04 -0300 Subject: [PATCH 3/5] Fixes --- packages/app/src/context/sdk.tsx | 44 +++++++++++++++------ packages/app/src/pages/directory-layout.tsx | 6 +-- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/packages/app/src/context/sdk.tsx b/packages/app/src/context/sdk.tsx index aa4820c4945..445558570f1 100644 --- a/packages/app/src/context/sdk.tsx +++ b/packages/app/src/context/sdk.tsx @@ -1,31 +1,49 @@ import { createOpencodeClient, type Event } from "@opencode-ai/sdk/v2/client" import { createSimpleContext } from "@opencode-ai/ui/context" import { createGlobalEmitter } from "@solid-primitives/event-bus" -import { onCleanup } from "solid-js" +import { createEffect, createMemo, on, onCleanup, type Accessor } from "solid-js" import { useGlobalSDK } from "./global-sdk" import { usePlatform } from "./platform" export const { use: useSDK, provider: SDKProvider } = createSimpleContext({ name: "SDK", - init: (props: { directory: string }) => { + init: (props: { directory: Accessor }) => { const platform = usePlatform() const globalSDK = useGlobalSDK() - const sdk = createOpencodeClient({ - baseUrl: globalSDK.url, - fetch: platform.fetch, - directory: props.directory, - throwOnError: true, - }) + + const client = createMemo(() => + createOpencodeClient({ + baseUrl: globalSDK.url, + fetch: platform.fetch, + directory: props.directory(), + throwOnError: true, + }), + ) const emitter = createGlobalEmitter<{ [key in Event["type"]]: Extract }>() - const unsub = globalSDK.event.on(props.directory, (event) => { - emitter.emit(event.type, event) - }) - onCleanup(unsub) + let unsub: VoidFunction | undefined + createEffect( + on(props.directory, (directory) => { + unsub?.() + unsub = globalSDK.event.on(directory, (event) => { + emitter.emit(event.type, event) + }) + }), + ) + onCleanup(() => unsub?.()) - return { directory: props.directory, client: sdk, event: emitter, url: globalSDK.url } + return { + get directory() { + return props.directory() + }, + get client() { + return client() + }, + event: emitter, + url: globalSDK.url, + } }, }) diff --git a/packages/app/src/pages/directory-layout.tsx b/packages/app/src/pages/directory-layout.tsx index dca02489a8a..894ca47127f 100644 --- a/packages/app/src/pages/directory-layout.tsx +++ b/packages/app/src/pages/directory-layout.tsx @@ -16,8 +16,8 @@ export default function Layout(props: ParentProps) { return base64Decode(params.dir!) }) return ( - - + + {iife(() => { const sync = useSync() @@ -40,7 +40,7 @@ export default function Layout(props: ParentProps) { return ( Date: Mon, 19 Jan 2026 19:26:05 -0300 Subject: [PATCH 4/5] WIP --- packages/app/src/context/global-sync.tsx | 12 ++++++++++++ packages/app/src/context/sync.tsx | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/app/src/context/global-sync.tsx b/packages/app/src/context/global-sync.tsx index c1ffea78ede..fc8e48fbb06 100644 --- a/packages/app/src/context/global-sync.tsx +++ b/packages/app/src/context/global-sync.tsx @@ -159,6 +159,17 @@ function createGlobalSync() { return childStore } + function reactive(directory: () => string) { + return { + get store() { + return child(directory())[0] + }, + get setStore() { + return child(directory())[1] + }, + } + } + function wait(directory: string) { return bootstrapPromises[directory] ?? Promise.resolve() } @@ -646,6 +657,7 @@ function createGlobalSync() { return globalStore.error }, child, + reactive, wait, bootstrap, project: { diff --git a/packages/app/src/context/sync.tsx b/packages/app/src/context/sync.tsx index 33129e1b475..7bdc9542e4c 100644 --- a/packages/app/src/context/sync.tsx +++ b/packages/app/src/context/sync.tsx @@ -12,7 +12,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ init: () => { const globalSync = useGlobalSync() const sdk = useSDK() - const [store, setStore] = globalSync.child(sdk.directory) + const { store, setStore } = globalSync.reactive(() => sdk.directory) const absolute = (path: string) => (store.path.directory + "/" + path).replace("//", "/") const chunk = 400 const inflight = new Map>() From 1c2b06c4bff4e41dccb1b5605b2a6cfd05565fed Mon Sep 17 00:00:00 2001 From: dbpolito Date: Mon, 19 Jan 2026 19:29:00 -0300 Subject: [PATCH 5/5] Tweak --- packages/app/src/context/global-sync.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/app/src/context/global-sync.tsx b/packages/app/src/context/global-sync.tsx index fc8e48fbb06..6300f51bcc0 100644 --- a/packages/app/src/context/global-sync.tsx +++ b/packages/app/src/context/global-sync.tsx @@ -149,7 +149,9 @@ function createGlobalSync() { part: {}, new: options?.new, }) - bootstrapPromises[directory] = bootstrapInstance(directory) + bootstrapPromises[directory] = bootstrapInstance(directory).finally(() => { + delete bootstrapPromises[directory] + }) } runWithOwner(owner, init) @@ -367,7 +369,9 @@ function createGlobalSync() { const [store, setStore] = child(directory) switch (event.type) { case "server.instance.disposed": { - bootstrapPromises[directory] = bootstrapInstance(directory) + bootstrapPromises[directory] = bootstrapInstance(directory).finally(() => { + delete bootstrapPromises[directory] + }) break } case "session.created": {