From 3bb546c94d6bb295bfeafdafbb9d34b7cc462560 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Wed, 10 Dec 2025 21:16:50 -0600 Subject: wip(desktop): progress --- packages/desktop/src/components/prompt-input.tsx | 97 ++++++----- packages/desktop/src/context/global-sync.tsx | 44 +++-- packages/desktop/src/context/layout.tsx | 22 ++- packages/desktop/src/context/sync.tsx | 23 ++- packages/desktop/src/pages/layout.tsx | 213 ++++++++++++++++++++++- 5 files changed, 331 insertions(+), 68 deletions(-) (limited to 'packages/desktop') diff --git a/packages/desktop/src/components/prompt-input.tsx b/packages/desktop/src/components/prompt-input.tsx index 22f2c1642..41af8644b 100644 --- a/packages/desktop/src/components/prompt-input.tsx +++ b/packages/desktop/src/components/prompt-input.tsx @@ -579,54 +579,61 @@ export const PromptInput: Component = (props) => {
-
+
Add more models from popular providers
- x?.id} - items={providers().popular()} - activeIcon="plus-small" - sortBy={(a, b) => { - if (popularProviders.includes(a.id) && popularProviders.includes(b.id)) - return popularProviders.indexOf(a.id) - popularProviders.indexOf(b.id) - return a.name.localeCompare(b.name) - }} - onSelect={(x) => { - layout.dialog.close("model") - }} - > - {(i) => ( -
- - {i.name} - - Recommended - - -
- Connect with Claude Pro/Max or API key -
-
-
- )} -
- +
+ x?.id} + items={providers().popular()} + activeIcon="plus-small" + sortBy={(a, b) => { + if (popularProviders.includes(a.id) && popularProviders.includes(b.id)) + return popularProviders.indexOf(a.id) - popularProviders.indexOf(b.id) + return a.name.localeCompare(b.name) + }} + onSelect={(x) => { + if (!x) return + layout.dialog.connect(x.id) + }} + > + {(i) => ( +
+ + {i.name} + + Recommended + + +
+ Connect with Claude Pro/Max or API key +
+
+
+ )} +
+ +
diff --git a/packages/desktop/src/context/global-sync.tsx b/packages/desktop/src/context/global-sync.tsx index 3a6062fb8..09dfb3a83 100644 --- a/packages/desktop/src/context/global-sync.tsx +++ b/packages/desktop/src/context/global-sync.tsx @@ -12,11 +12,13 @@ import type { Todo, SessionStatus, ProviderListResponse, + ProviderAuthResponse, } from "@opencode-ai/sdk/v2" import { createStore, produce, reconcile } from "solid-js/store" import { Binary } from "@opencode-ai/util/binary" import { createSimpleContext } from "@opencode-ai/ui/context" import { useGlobalSDK } from "./global-sdk" +import { onMount } from "solid-js" type State = { ready: boolean @@ -54,11 +56,13 @@ export const { use: useGlobalSync, provider: GlobalSyncProvider } = createSimple ready: boolean project: Project[] provider: ProviderListResponse + provider_auth: ProviderAuthResponse children: Record }>({ ready: false, project: [], provider: { all: [], connected: [], default: {} }, + provider_auth: {}, children: {}, }) @@ -113,6 +117,10 @@ export const { use: useGlobalSync, provider: GlobalSyncProvider } = createSimple const [store, setStore] = child(directory) switch (event.type) { + // case "server.instance.disposed": { + // bootstrap() + // break + // } case "session.updated": { const result = Binary.search(store.session, event.properties.info.id, (s) => s.id) if (result.found) { @@ -181,19 +189,28 @@ export const { use: useGlobalSync, provider: GlobalSyncProvider } = createSimple } }) - Promise.all([ - sdk.client.project.list().then(async (x) => { - setGlobalStore( - "project", - x - .data!.filter((p) => !p.worktree.includes("opencode-test") && p.vcs) - .sort((a, b) => a.id.localeCompare(b.id)), - ) - }), - sdk.client.provider.list().then((x) => { - setGlobalStore("provider", x.data ?? {}) - }), - ]).then(() => setGlobalStore("ready", true)) + async function bootstrap() { + return Promise.all([ + sdk.client.project.list().then(async (x) => { + setGlobalStore( + "project", + x + .data!.filter((p) => !p.worktree.includes("opencode-test") && p.vcs) + .sort((a, b) => a.id.localeCompare(b.id)), + ) + }), + sdk.client.provider.list().then((x) => { + setGlobalStore("provider", x.data ?? {}) + }), + sdk.client.provider.auth().then((x) => { + setGlobalStore("provider_auth", x.data ?? {}) + }), + ]).then(() => setGlobalStore("ready", true)) + } + + onMount(() => { + bootstrap() + }) return { data: globalStore, @@ -201,6 +218,7 @@ export const { use: useGlobalSync, provider: GlobalSyncProvider } = createSimple return globalStore.ready }, child, + bootstrap, } }, }) diff --git a/packages/desktop/src/context/layout.tsx b/packages/desktop/src/context/layout.tsx index 5530ad28f..d00e101b8 100644 --- a/packages/desktop/src/context/layout.tsx +++ b/packages/desktop/src/context/layout.tsx @@ -1,5 +1,5 @@ import { createStore } from "solid-js/store" -import { createMemo, onMount } from "solid-js" +import { batch, createMemo, onMount } from "solid-js" import { createSimpleContext } from "@opencode-ai/ui/context" import { makePersisted } from "@solid-primitives/storage" import { useGlobalSync } from "./global-sync" @@ -19,6 +19,8 @@ const PASTEL_COLORS = [ "#C1E1C1", // pastel mint ] +type Dialog = "provider" | "model" | "connect" + export const { use: useLayout, provider: LayoutProvider } = createSimpleContext({ name: "Layout", init: () => { @@ -44,8 +46,11 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( }, ) const [ephemeral, setEphemeral] = createStore({ + connect: { + provider: undefined as undefined | string, + }, dialog: { - open: undefined as undefined | "provider" | "model", + open: undefined as undefined | Dialog, }, }) const usedColors = new Set() @@ -169,14 +174,23 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( }, dialog: { opened: createMemo(() => ephemeral.dialog?.open), - open(dialog: "provider" | "model") { + open(dialog: Dialog) { setEphemeral("dialog", "open", dialog) }, - close(dialog: "provider" | "model") { + close(dialog: Dialog) { if (ephemeral.dialog?.open === dialog) { setEphemeral("dialog", "open", undefined) } }, + connect(provider: string) { + batch(() => { + setEphemeral("dialog", "open", "connect") + setEphemeral("connect", "provider", provider) + }) + }, + }, + connect: { + provider: createMemo(() => ephemeral.connect.provider), }, } }, diff --git a/packages/desktop/src/context/sync.tsx b/packages/desktop/src/context/sync.tsx index 1a11cd599..d64fcce2a 100644 --- a/packages/desktop/src/context/sync.tsx +++ b/packages/desktop/src/context/sync.tsx @@ -1,5 +1,5 @@ import { produce } from "solid-js/store" -import { createMemo } from "solid-js" +import { createMemo, onMount } from "solid-js" import { Binary } from "@opencode-ai/util/binary" import { createSimpleContext } from "@opencode-ai/ui/context" import { useGlobalSync } from "./global-sync" @@ -31,7 +31,24 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ node: () => sdk.client.file.list({ path: "/" }).then((x) => setStore("node", x.data!)), } - Promise.all(Object.values(load).map((p) => p())).then(() => setStore("ready", true)) + async function bootstrap() { + return Promise.all(Object.values(load).map((p) => p())).then(() => setStore("ready", true)) + } + + onMount(() => { + bootstrap() + }) + + sdk.event.listen((e) => { + if (e.name !== sdk.directory) return + const event = e.details + switch (event.type) { + case "server.instance.disposed": { + bootstrap() + break + } + } + }) const absolute = (path: string) => (store.path.directory + "/" + path).replace("//", "/") @@ -82,7 +99,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ }, more: createMemo(() => store.session.length >= store.limit), }, - load, + bootstrap, absolute, get directory() { return store.path.directory diff --git a/packages/desktop/src/pages/layout.tsx b/packages/desktop/src/pages/layout.tsx index 10d4cbfda..0ba6c0a2d 100644 --- a/packages/desktop/src/pages/layout.tsx +++ b/packages/desktop/src/pages/layout.tsx @@ -17,7 +17,7 @@ import { DiffChanges } from "@opencode-ai/ui/diff-changes" import { getFilename } from "@opencode-ai/util/path" import { Select } from "@opencode-ai/ui/select" import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu" -import { Session, Project } from "@opencode-ai/sdk/v2/client" +import { Session, Project, ProviderAuthMethod } from "@opencode-ai/sdk/v2/client" import { usePlatform } from "@/context/platform" import { createStore } from "solid-js/store" import { @@ -34,6 +34,11 @@ import { SelectDialog } from "@opencode-ai/ui/select-dialog" import { Tag } from "@opencode-ai/ui/tag" import { IconName } from "@opencode-ai/ui/icons/provider" import { popularProviders, useProviders } from "@/hooks/use-providers" +import { Dialog } from "@opencode-ai/ui/dialog" +import { iife } from "@opencode-ai/util/iife" +import { List, ListRef } from "@opencode-ai/ui/list" +import { Input } from "@opencode-ai/ui/input" +import { useGlobalSDK } from "@/context/global-sdk" export default function Layout(props: ParentProps) { const [store, setStore] = createStore({ @@ -42,6 +47,7 @@ export default function Layout(props: ParentProps) { }) const params = useParams() + const globalSDK = useGlobalSDK() const globalSync = useGlobalSync() const layout = useLayout() const platform = usePlatform() @@ -562,7 +568,6 @@ export default function Layout(props: ParentProps) { activeIcon="plus-small" key={(x) => x?.id} items={providers().all} - // current={local.model.current()} filterKeys={["id", "name"]} groupBy={(x) => (popularProviders.includes(x.id) ? "Popular" : "Other")} sortBy={(a, b) => { @@ -575,7 +580,10 @@ export default function Layout(props: ParentProps) { if (b.category === "Popular" && a.category !== "Popular") return 1 return 0 }} - // onSelect={(x) => } + onSelect={(x) => { + if (!x) return + layout.dialog.connect(x.id) + }} onOpenChange={(open) => { if (open) { layout.dialog.open("provider") @@ -607,6 +615,205 @@ export default function Layout(props: ParentProps) { )} + + {iife(() => { + const [store, setStore] = createStore({ + method: undefined as undefined | ProviderAuthMethod, + }) + const providerID = layout.connect.provider()! + const provider = globalSync.data.provider.all.find((x) => x.id === providerID)! + const methods = globalSync.data.provider_auth[providerID] ?? [ + { + type: "api", + label: "API key", + }, + ] + if (methods.length === 1) { + setStore("method", methods[0]) + } + + let listRef: ListRef | undefined + const handleKey = (e: KeyboardEvent) => { + if (e.key === "Escape") return + listRef?.onKeyDown(e) + } + + return ( + { + if (open) { + layout.dialog.open("connect") + } else { + layout.dialog.close("connect") + } + }} + > + + + { + if (store.method && methods.length > 1) { + setStore("method", undefined) + return + } + layout.dialog.open("provider") + }} + /> + + + + +
+
+ +
Connect {provider.name}
+
+ +
Select login method for {provider.name}.
+
+ + (listRef = ref)} + items={methods} + key={(m) => m?.label} + onSelect={(method) => { + if (!method) return + setStore("method", method) + + if (method.type === "oauth") { + // const result = await sdk.client.provider.oauth.authorize({ + // providerID: provider.id, + // method: index, + // }) + // if (result.data?.method === "code") { + // dialog.replace(() => ( + // + // )) + // } + // if (result.data?.method === "auto") { + // dialog.replace(() => ( + // + // )) + // } + } + if (method.type === "api") { + // return dialog.replace(() => ) + } + }} + > + {(i) => ( +
+ {/* TODO: add checkmark thing */} + {i.label} +
+ )} +
+
+
+ + {iife(() => { + const [formStore, setFormStore] = createStore({ + value: "", + error: undefined as string | undefined, + }) + + async function handleSubmit(e: SubmitEvent) { + e.preventDefault() + + const form = e.currentTarget as HTMLFormElement + const formData = new FormData(form) + const apiKey = formData.get("apiKey") as string + + if (!apiKey?.trim()) { + setFormStore("error", "API key is required") + return + } + + setFormStore("error", undefined) + globalSDK.client.auth.set({ + providerID, + auth: { + type: "api", + key: apiKey, + }, + }) + await globalSDK.client.instance.dispose() + } + + return ( +
+ + +
+
+ OpenCode Zen gives you access to a curated set of reliable optimized models for + coding agents. +
+
+ With a single API key you’ll get access to models such as Claude, GPT, Gemini, GLM + and more. +
+
+ Visit{" "} + {" "} + to collect your API key. +
+
+
+ +
+ Enter your {provider.name} API key to connect your account and use {provider.name}{" "} + models in OpenCode. +
+
+
+
+ + +
+
+ ) + })} +
+
+
+
+ ) + })} +
) -- cgit v1.2.3 From 1b331548ba428a05c48895bfa374f1f140eb4c38 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Wed, 10 Dec 2025 21:21:36 -0600 Subject: wip(desktop): progress --- packages/desktop/src/context/global-sync.tsx | 8 ++++---- packages/desktop/src/pages/layout.tsx | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'packages/desktop') diff --git a/packages/desktop/src/context/global-sync.tsx b/packages/desktop/src/context/global-sync.tsx index 09dfb3a83..770275a5c 100644 --- a/packages/desktop/src/context/global-sync.tsx +++ b/packages/desktop/src/context/global-sync.tsx @@ -97,6 +97,10 @@ export const { use: useGlobalSync, provider: GlobalSyncProvider } = createSimple if (directory === "global") { switch (event.type) { + case "global.disposed": { + bootstrap() + break + } case "project.updated": { const result = Binary.search(globalStore.project, event.properties.id, (s) => s.id) if (result.found) { @@ -117,10 +121,6 @@ export const { use: useGlobalSync, provider: GlobalSyncProvider } = createSimple const [store, setStore] = child(directory) switch (event.type) { - // case "server.instance.disposed": { - // bootstrap() - // break - // } case "session.updated": { const result = Binary.search(store.session, event.properties.info.id, (s) => s.id) if (result.found) { diff --git a/packages/desktop/src/pages/layout.tsx b/packages/desktop/src/pages/layout.tsx index 0ba6c0a2d..0bc6e9e09 100644 --- a/packages/desktop/src/pages/layout.tsx +++ b/packages/desktop/src/pages/layout.tsx @@ -745,14 +745,14 @@ export default function Layout(props: ParentProps) { } setFormStore("error", undefined) - globalSDK.client.auth.set({ + await globalSDK.client.auth.set({ providerID, auth: { type: "api", key: apiKey, }, }) - await globalSDK.client.instance.dispose() + await globalSDK.client.global.dispose() } return ( -- cgit v1.2.3 From 740aa8e54191ba67b3d89596938757c1932f3fb1 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Wed, 10 Dec 2025 21:29:03 -0600 Subject: wip(desktop): progress --- packages/desktop/src/context/sync.tsx | 1 + 1 file changed, 1 insertion(+) (limited to 'packages/desktop') diff --git a/packages/desktop/src/context/sync.tsx b/packages/desktop/src/context/sync.tsx index d64fcce2a..d1acc26ab 100644 --- a/packages/desktop/src/context/sync.tsx +++ b/packages/desktop/src/context/sync.tsx @@ -42,6 +42,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ sdk.event.listen((e) => { if (e.name !== sdk.directory) return const event = e.details + console.log(event) switch (event.type) { case "server.instance.disposed": { bootstrap() -- cgit v1.2.3 From 85c0311d38c47c41e89f6b9cd7d3a0cfc4348841 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Wed, 10 Dec 2025 21:34:14 -0600 Subject: wip(desktop): progress --- packages/desktop/src/context/sync.tsx | 1 - 1 file changed, 1 deletion(-) (limited to 'packages/desktop') diff --git a/packages/desktop/src/context/sync.tsx b/packages/desktop/src/context/sync.tsx index d1acc26ab..9c3abd731 100644 --- a/packages/desktop/src/context/sync.tsx +++ b/packages/desktop/src/context/sync.tsx @@ -40,7 +40,6 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ }) sdk.event.listen((e) => { - if (e.name !== sdk.directory) return const event = e.details console.log(event) switch (event.type) { -- cgit v1.2.3 From 1980113ee4305844803f866aef05d742f7cffd47 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Thu, 11 Dec 2025 03:13:08 -0600 Subject: wip(desktop): progress --- packages/desktop/src/context/global-sync.tsx | 75 ++++++++++++++++++++-------- packages/desktop/src/context/layout.tsx | 32 +++++++++++- packages/desktop/src/context/sync.tsx | 50 +++---------------- packages/desktop/src/pages/layout.tsx | 5 +- packages/ui/src/components/list.tsx | 11 ++-- 5 files changed, 101 insertions(+), 72 deletions(-) (limited to 'packages/desktop') diff --git a/packages/desktop/src/context/global-sync.tsx b/packages/desktop/src/context/global-sync.tsx index 770275a5c..2a24a845c 100644 --- a/packages/desktop/src/context/global-sync.tsx +++ b/packages/desktop/src/context/global-sync.tsx @@ -1,19 +1,20 @@ -import type { - Message, - Agent, - Session, - Part, - Config, - Path, - File, - FileNode, - Project, - FileDiff, - Todo, - SessionStatus, - ProviderListResponse, - ProviderAuthResponse, -} from "@opencode-ai/sdk/v2" +import { + type Message, + type Agent, + type Session, + type Part, + type Config, + type Path, + type File, + type FileNode, + type Project, + type FileDiff, + type Todo, + type SessionStatus, + type ProviderListResponse, + type ProviderAuthResponse, + createOpencodeClient, +} from "@opencode-ai/sdk/v2/client" import { createStore, produce, reconcile } from "solid-js/store" import { Binary } from "@opencode-ai/util/binary" import { createSimpleContext } from "@opencode-ai/ui/context" @@ -51,7 +52,7 @@ type State = { export const { use: useGlobalSync, provider: GlobalSyncProvider } = createSimpleContext({ name: "GlobalSync", init: () => { - const sdk = useGlobalSDK() + const globalSDK = useGlobalSDK() const [globalStore, setGlobalStore] = createStore<{ ready: boolean project: Project[] @@ -66,6 +67,33 @@ export const { use: useGlobalSync, provider: GlobalSyncProvider } = createSimple children: {}, }) + async function bootstrapInstance(directory: string) { + const [store, setStore] = child(directory) + const sdk = createOpencodeClient({ + baseUrl: globalSDK.url, + directory, + }) + const load = { + project: () => sdk.project.current().then((x) => setStore("project", x.data!.id)), + provider: () => sdk.provider.list().then((x) => setStore("provider", x.data!)), + path: () => sdk.path.get().then((x) => setStore("path", x.data!)), + agent: () => sdk.app.agents().then((x) => setStore("agent", x.data ?? [])), + session: () => + sdk.session.list().then((x) => { + const sessions = (x.data ?? []) + .slice() + .sort((a, b) => a.id.localeCompare(b.id)) + .slice(0, store.limit) + setStore("session", sessions) + }), + status: () => sdk.session.status().then((x) => setStore("session_status", x.data!)), + config: () => sdk.config.get().then((x) => setStore("config", x.data!)), + changes: () => sdk.file.status().then((x) => setStore("changes", x.data!)), + node: () => sdk.file.list({ path: "/" }).then((x) => setStore("node", x.data!)), + } + await Promise.all(Object.values(load).map((p) => p())).then(() => setStore("ready", true)) + } + const children: Record>> = {} function child(directory: string) { if (!children[directory]) { @@ -87,11 +115,12 @@ export const { use: useGlobalSync, provider: GlobalSyncProvider } = createSimple changes: [], }) children[directory] = createStore(globalStore.children[directory]) + bootstrapInstance(directory) } return children[directory] } - sdk.event.listen((e) => { + globalSDK.event.listen((e) => { const directory = e.name const event = e.details @@ -121,6 +150,10 @@ export const { use: useGlobalSync, provider: GlobalSyncProvider } = createSimple const [store, setStore] = child(directory) switch (event.type) { + case "server.instance.disposed": { + bootstrapInstance(directory) + break + } case "session.updated": { const result = Binary.search(store.session, event.properties.info.id, (s) => s.id) if (result.found) { @@ -191,7 +224,7 @@ export const { use: useGlobalSync, provider: GlobalSyncProvider } = createSimple async function bootstrap() { return Promise.all([ - sdk.client.project.list().then(async (x) => { + globalSDK.client.project.list().then(async (x) => { setGlobalStore( "project", x @@ -199,10 +232,10 @@ export const { use: useGlobalSync, provider: GlobalSyncProvider } = createSimple .sort((a, b) => a.id.localeCompare(b.id)), ) }), - sdk.client.provider.list().then((x) => { + globalSDK.client.provider.list().then((x) => { setGlobalStore("provider", x.data ?? {}) }), - sdk.client.provider.auth().then((x) => { + globalSDK.client.provider.auth().then((x) => { setGlobalStore("provider_auth", x.data ?? {}) }), ]).then(() => setGlobalStore("ready", true)) diff --git a/packages/desktop/src/context/layout.tsx b/packages/desktop/src/context/layout.tsx index d00e101b8..d4a8875f7 100644 --- a/packages/desktop/src/context/layout.tsx +++ b/packages/desktop/src/context/layout.tsx @@ -1,4 +1,4 @@ -import { createStore } from "solid-js/store" +import { createStore, produce } from "solid-js/store" import { batch, createMemo, onMount } from "solid-js" import { createSimpleContext } from "@opencode-ai/ui/context" import { makePersisted } from "@solid-primitives/storage" @@ -48,6 +48,8 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( const [ephemeral, setEphemeral] = createStore({ connect: { provider: undefined as undefined | string, + state: undefined as undefined | "pending" | "complete" | "error", + error: undefined as undefined | string, }, dialog: { open: undefined as undefined | Dialog, @@ -176,21 +178,47 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( opened: createMemo(() => ephemeral.dialog?.open), open(dialog: Dialog) { setEphemeral("dialog", "open", dialog) + if (dialog !== "connect") { + setEphemeral("connect", {}) + } }, close(dialog: Dialog) { if (ephemeral.dialog?.open === dialog) { setEphemeral("dialog", "open", undefined) + if (dialog === "connect") { + setEphemeral("connect", {}) + } } }, connect(provider: string) { batch(() => { setEphemeral("dialog", "open", "connect") - setEphemeral("connect", "provider", provider) + setEphemeral("connect", { provider, state: "pending" }) }) }, }, connect: { provider: createMemo(() => ephemeral.connect.provider), + state: createMemo(() => ephemeral.connect.state), + complete() { + setEphemeral( + produce((state) => { + state.dialog.open = "model" + state.connect.state = "complete" + }), + ) + }, + error(message: string) { + setEphemeral( + produce((state) => { + state.connect.state = "error" + state.connect.error = message + }), + ) + }, + clear() { + setEphemeral("connect", {}) + }, }, } }, diff --git a/packages/desktop/src/context/sync.tsx b/packages/desktop/src/context/sync.tsx index 9c3abd731..85758c5b6 100644 --- a/packages/desktop/src/context/sync.tsx +++ b/packages/desktop/src/context/sync.tsx @@ -1,5 +1,5 @@ import { produce } from "solid-js/store" -import { createMemo, onMount } from "solid-js" +import { createMemo } from "solid-js" import { Binary } from "@opencode-ai/util/binary" import { createSimpleContext } from "@opencode-ai/ui/context" import { useGlobalSync } from "./global-sync" @@ -11,45 +11,6 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ const globalSync = useGlobalSync() const sdk = useSDK() const [store, setStore] = globalSync.child(sdk.directory) - - const load = { - project: () => sdk.client.project.current().then((x) => setStore("project", x.data!.id)), - provider: () => sdk.client.provider.list().then((x) => setStore("provider", x.data!)), - path: () => sdk.client.path.get().then((x) => setStore("path", x.data!)), - agent: () => sdk.client.app.agents().then((x) => setStore("agent", x.data ?? [])), - session: () => - sdk.client.session.list().then((x) => { - const sessions = (x.data ?? []) - .slice() - .sort((a, b) => a.id.localeCompare(b.id)) - .slice(0, store.limit) - setStore("session", sessions) - }), - status: () => sdk.client.session.status().then((x) => setStore("session_status", x.data!)), - config: () => sdk.client.config.get().then((x) => setStore("config", x.data!)), - changes: () => sdk.client.file.status().then((x) => setStore("changes", x.data!)), - node: () => sdk.client.file.list({ path: "/" }).then((x) => setStore("node", x.data!)), - } - - async function bootstrap() { - return Promise.all(Object.values(load).map((p) => p())).then(() => setStore("ready", true)) - } - - onMount(() => { - bootstrap() - }) - - sdk.event.listen((e) => { - const event = e.details - console.log(event) - switch (event.type) { - case "server.instance.disposed": { - bootstrap() - break - } - } - }) - const absolute = (path: string) => (store.path.directory + "/" + path).replace("//", "/") return { @@ -95,11 +56,16 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ }, fetch: async (count = 10) => { setStore("limit", (x) => x + count) - await load.session() + await sdk.client.session.list().then((x) => { + const sessions = (x.data ?? []) + .slice() + .sort((a, b) => a.id.localeCompare(b.id)) + .slice(0, store.limit) + setStore("session", sessions) + }) }, more: createMemo(() => store.session.length >= store.limit), }, - bootstrap, absolute, get directory() { return store.path.directory diff --git a/packages/desktop/src/pages/layout.tsx b/packages/desktop/src/pages/layout.tsx index 0bc6e9e09..5f0b26f6b 100644 --- a/packages/desktop/src/pages/layout.tsx +++ b/packages/desktop/src/pages/layout.tsx @@ -440,7 +440,7 @@ export default function Layout(props: ParentProps) {