diff options
| author | Adam <[email protected]> | 2025-10-23 15:27:31 -0500 |
|---|---|---|
| committer | Adam <[email protected]> | 2025-10-24 12:16:32 -0500 |
| commit | 3eb2db98ed0a9c266e1bf00544e460cb0633b368 (patch) | |
| tree | eb04fea563b3a3b74a3d89ca9500e92cf4b908c8 /packages/desktop/src/context/sync.tsx | |
| parent | 35dec0649db8f46bffd7121af9cd301668e69e8c (diff) | |
| download | opencode-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.tsx | 301 |
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, + } + }, +}) |
