summaryrefslogtreecommitdiffhomepage
path: root/packages/desktop/src/context/sync.tsx
diff options
context:
space:
mode:
authorAdam <[email protected]>2025-10-23 15:27:31 -0500
committerAdam <[email protected]>2025-10-24 12:16:32 -0500
commit3eb2db98ed0a9c266e1bf00544e460cb0633b368 (patch)
treeeb04fea563b3a3b74a3d89ca9500e92cf4b908c8 /packages/desktop/src/context/sync.tsx
parent35dec0649db8f46bffd7121af9cd301668e69e8c (diff)
downloadopencode-3eb2db98ed0a9c266e1bf00544e460cb0633b368.tar.gz
opencode-3eb2db98ed0a9c266e1bf00544e460cb0633b368.zip
wip: desktop work
Diffstat (limited to 'packages/desktop/src/context/sync.tsx')
-rw-r--r--packages/desktop/src/context/sync.tsx301
1 files changed, 143 insertions, 158 deletions
diff --git a/packages/desktop/src/context/sync.tsx b/packages/desktop/src/context/sync.tsx
index 5ba6b1af2..0fea4a421 100644
--- a/packages/desktop/src/context/sync.tsx
+++ b/packages/desktop/src/context/sync.tsx
@@ -1,177 +1,162 @@
import type { Message, Agent, Provider, Session, Part, Config, Path, File, FileNode, Project } from "@opencode-ai/sdk"
import { createStore, produce, reconcile } from "solid-js/store"
-import { createContext, createMemo, Show, useContext, type ParentProps } from "solid-js"
-import { useSDK, useEvent } from "@/context"
+import { createMemo } from "solid-js"
import { Binary } from "@/utils/binary"
+import { createSimpleContext } from "./helper"
+import { useSDK } from "./sdk"
-function init() {
- const [store, setStore] = createStore<{
- ready: boolean
- provider: Provider[]
- agent: Agent[]
- project: Project
- config: Config
- path: Path
- session: Session[]
- message: {
- [sessionID: string]: Message[]
- }
- part: {
- [messageID: string]: Part[]
- }
- node: FileNode[]
- changes: File[]
- }>({
- project: { id: "", worktree: "", time: { created: 0, initialized: 0 } },
- config: {},
- path: { state: "", config: "", worktree: "", directory: "" },
- ready: false,
- agent: [],
- provider: [],
- session: [],
- message: {},
- part: {},
- node: [],
- changes: [],
- })
-
- const bus = useEvent()
- bus.listen((event) => {
- switch (event.type) {
- case "session.updated": {
- const result = Binary.search(store.session, event.properties.info.id, (s) => s.id)
- if (result.found) {
- setStore("session", result.index, reconcile(event.properties.info))
- break
- }
- setStore(
- "session",
- produce((draft) => {
- draft.splice(result.index, 0, event.properties.info)
- }),
- )
- break
+export const { use: useSync, provider: SyncProvider } = createSimpleContext({
+ name: "Sync",
+ init: () => {
+ const [store, setStore] = createStore<{
+ ready: boolean
+ provider: Provider[]
+ agent: Agent[]
+ project: Project
+ config: Config
+ path: Path
+ session: Session[]
+ message: {
+ [sessionID: string]: Message[]
}
- case "message.updated": {
- const messages = store.message[event.properties.info.sessionID]
- if (!messages) {
- setStore("message", event.properties.info.sessionID, [event.properties.info])
- break
- }
- const result = Binary.search(messages, event.properties.info.id, (m) => m.id)
- if (result.found) {
- setStore("message", event.properties.info.sessionID, result.index, reconcile(event.properties.info))
+ part: {
+ [messageID: string]: Part[]
+ }
+ node: FileNode[]
+ changes: File[]
+ }>({
+ project: { id: "", worktree: "", time: { created: 0, initialized: 0 } },
+ config: {},
+ path: { state: "", config: "", worktree: "", directory: "" },
+ ready: false,
+ agent: [],
+ provider: [],
+ session: [],
+ message: {},
+ part: {},
+ node: [],
+ changes: [],
+ })
+
+ const sdk = useSDK()
+ sdk.event.listen((e) => {
+ const event = e.details
+ switch (event.type) {
+ case "session.updated": {
+ const result = Binary.search(store.session, event.properties.info.id, (s) => s.id)
+ if (result.found) {
+ setStore("session", result.index, reconcile(event.properties.info))
+ break
+ }
+ setStore(
+ "session",
+ produce((draft) => {
+ draft.splice(result.index, 0, event.properties.info)
+ }),
+ )
break
}
- setStore(
- "message",
- event.properties.info.sessionID,
- produce((draft) => {
- draft.splice(result.index, 0, event.properties.info)
- }),
- )
- break
- }
- case "message.part.updated": {
- const parts = store.part[event.properties.part.messageID]
- if (!parts) {
- setStore("part", event.properties.part.messageID, [event.properties.part])
+ case "message.updated": {
+ const messages = store.message[event.properties.info.sessionID]
+ if (!messages) {
+ setStore("message", event.properties.info.sessionID, [event.properties.info])
+ break
+ }
+ const result = Binary.search(messages, event.properties.info.id, (m) => m.id)
+ if (result.found) {
+ setStore("message", event.properties.info.sessionID, result.index, reconcile(event.properties.info))
+ break
+ }
+ setStore(
+ "message",
+ event.properties.info.sessionID,
+ produce((draft) => {
+ draft.splice(result.index, 0, event.properties.info)
+ }),
+ )
break
}
- const result = Binary.search(parts, event.properties.part.id, (p) => p.id)
- if (result.found) {
- setStore("part", event.properties.part.messageID, result.index, reconcile(event.properties.part))
+ case "message.part.updated": {
+ const parts = store.part[event.properties.part.messageID]
+ if (!parts) {
+ setStore("part", event.properties.part.messageID, [event.properties.part])
+ break
+ }
+ const result = Binary.search(parts, event.properties.part.id, (p) => p.id)
+ if (result.found) {
+ setStore("part", event.properties.part.messageID, result.index, reconcile(event.properties.part))
+ break
+ }
+ setStore(
+ "part",
+ event.properties.part.messageID,
+ produce((draft) => {
+ draft.splice(result.index, 0, event.properties.part)
+ }),
+ )
break
}
- setStore(
- "part",
- event.properties.part.messageID,
- produce((draft) => {
- draft.splice(result.index, 0, event.properties.part)
- }),
- )
- break
}
- }
- })
-
- const sdk = useSDK()
+ })
- const load = {
- project: () => sdk.project.current().then((x) => setStore("project", x.data!)),
- provider: () => sdk.config.providers().then((x) => setStore("provider", x.data!.providers)),
- 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) =>
- setStore(
- "session",
- (x.data ?? []).slice().sort((a, b) => a.id.localeCompare(b.id)),
+ const load = {
+ project: () => sdk.client.project.current().then((x) => setStore("project", x.data!)),
+ provider: () => sdk.client.config.providers().then((x) => setStore("provider", x.data!.providers)),
+ 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) =>
+ setStore(
+ "session",
+ (x.data ?? []).slice().sort((a, b) => a.id.localeCompare(b.id)),
+ ),
),
- ),
- config: () => sdk.config.get().then((x) => setStore("config", x.data!)),
- changes: () => sdk.file.status().then((x) => setStore("changes", x.data!)),
- node: () => sdk.file.list({ query: { path: "/" } }).then((x) => setStore("node", 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({ query: { path: "/" } }).then((x) => setStore("node", x.data!)),
+ }
- Promise.all(Object.values(load).map((p) => p())).then(() => setStore("ready", true))
+ Promise.all(Object.values(load).map((p) => p())).then(() => setStore("ready", true))
- const sanitizer = createMemo(() => new RegExp(`${store.path.directory}/`, "g"))
- const sanitize = (text: string) => text.replace(sanitizer(), "")
- const absolute = (path: string) => (store.path.directory + "/" + path).replace("//", "/")
+ const sanitizer = createMemo(() => new RegExp(`${store.path.directory}/`, "g"))
+ const sanitize = (text: string) => text.replace(sanitizer(), "")
+ const absolute = (path: string) => (store.path.directory + "/" + path).replace("//", "/")
- return {
- data: store,
- set: setStore,
- session: {
- get(sessionID: string) {
- const match = Binary.search(store.session, sessionID, (s) => s.id)
- if (match.found) return store.session[match.index]
- return undefined
+ return {
+ data: store,
+ set: setStore,
+ get ready() {
+ return store.ready
},
- async sync(sessionID: string) {
- const [session, messages] = await Promise.all([
- sdk.session.get({ path: { id: sessionID } }),
- sdk.session.messages({ path: { id: sessionID } }),
- ])
- setStore(
- produce((draft) => {
- const match = Binary.search(draft.session, sessionID, (s) => s.id)
- draft.session[match.index] = session.data!
- draft.message[sessionID] = messages
- .data!.map((x) => x.info)
- .slice()
- .sort((a, b) => a.id.localeCompare(b.id))
- for (const message of messages.data!) {
- draft.part[message.info.id] = message.parts.slice().sort((a, b) => a.id.localeCompare(b.id))
- }
- }),
- )
+ session: {
+ get(sessionID: string) {
+ const match = Binary.search(store.session, sessionID, (s) => s.id)
+ if (match.found) return store.session[match.index]
+ return undefined
+ },
+ async sync(sessionID: string) {
+ const [session, messages] = await Promise.all([
+ sdk.client.session.get({ path: { id: sessionID } }),
+ sdk.client.session.messages({ path: { id: sessionID } }),
+ ])
+ setStore(
+ produce((draft) => {
+ const match = Binary.search(draft.session, sessionID, (s) => s.id)
+ draft.session[match.index] = session.data!
+ draft.message[sessionID] = messages
+ .data!.map((x) => x.info)
+ .slice()
+ .sort((a, b) => a.id.localeCompare(b.id))
+ for (const message of messages.data!) {
+ draft.part[message.info.id] = message.parts.slice().sort((a, b) => a.id.localeCompare(b.id))
+ }
+ }),
+ )
+ },
},
- },
- load,
- absolute,
- sanitize,
- }
-}
-
-type SyncContext = ReturnType<typeof init>
-
-const ctx = createContext<SyncContext>()
-
-export function SyncProvider(props: ParentProps) {
- const value = init()
- return (
- <Show when={value.data.ready}>
- <ctx.Provider value={value}>{props.children}</ctx.Provider>
- </Show>
- )
-}
-
-export function useSync() {
- const value = useContext(ctx)
- if (!value) {
- throw new Error("useSync must be used within a SyncProvider")
- }
- return value
-}
+ load,
+ absolute,
+ sanitize,
+ }
+ },
+})