sync.tsx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import { produce } from "solid-js/store"
  2. import { createMemo } from "solid-js"
  3. import { Binary } from "@opencode-ai/util/binary"
  4. import { createSimpleContext } from "@opencode-ai/ui/context"
  5. import { useGlobalSync } from "./global-sync"
  6. import { useSDK } from "./sdk"
  7. export const { use: useSync, provider: SyncProvider } = createSimpleContext({
  8. name: "Sync",
  9. init: () => {
  10. const globalSync = useGlobalSync()
  11. const sdk = useSDK()
  12. const [store, setStore] = globalSync.child(sdk.directory)
  13. const absolute = (path: string) => (store.path.directory + "/" + path).replace("//", "/")
  14. return {
  15. data: store,
  16. set: setStore,
  17. get ready() {
  18. return store.ready
  19. },
  20. get project() {
  21. const match = Binary.search(globalSync.data.project, store.project, (p) => p.id)
  22. if (match.found) return globalSync.data.project[match.index]
  23. return undefined
  24. },
  25. session: {
  26. get(sessionID: string) {
  27. const match = Binary.search(store.session, sessionID, (s) => s.id)
  28. if (match.found) return store.session[match.index]
  29. return undefined
  30. },
  31. async sync(sessionID: string, _isRetry = false) {
  32. const [session, messages, todo, diff] = await Promise.all([
  33. sdk.client.session.get({ sessionID }, { throwOnError: true }),
  34. sdk.client.session.messages({ sessionID, limit: 100 }),
  35. sdk.client.session.todo({ sessionID }),
  36. sdk.client.session.diff({ sessionID }),
  37. ])
  38. setStore(
  39. produce((draft) => {
  40. const match = Binary.search(draft.session, sessionID, (s) => s.id)
  41. if (match.found) draft.session[match.index] = session.data!
  42. if (!match.found) draft.session.splice(match.index, 0, session.data!)
  43. draft.todo[sessionID] = todo.data ?? []
  44. draft.message[sessionID] = messages
  45. .data!.map((x) => x.info)
  46. .slice()
  47. .sort((a, b) => a.id.localeCompare(b.id))
  48. for (const message of messages.data!) {
  49. draft.part[message.info.id] = message.parts.slice().sort((a, b) => a.id.localeCompare(b.id))
  50. }
  51. draft.session_diff[sessionID] = diff.data ?? []
  52. }),
  53. )
  54. },
  55. fetch: async (count = 10) => {
  56. setStore("limit", (x) => x + count)
  57. await sdk.client.session.list().then((x) => {
  58. const sessions = (x.data ?? [])
  59. .slice()
  60. .sort((a, b) => a.id.localeCompare(b.id))
  61. .slice(0, store.limit)
  62. setStore("session", sessions)
  63. })
  64. },
  65. more: createMemo(() => store.session.length >= store.limit),
  66. },
  67. absolute,
  68. get directory() {
  69. return store.path.directory
  70. },
  71. }
  72. },
  73. })