/
Alex_Ural
/
opencode
Обзор
Документация
Войти
/
Alex_Ural
/
opencode
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
dev
packages/app/src/context/sync.tsx
119 строк
3 KB
Brendan Allan
refactor(app): rename cached context accessors (#33627)
24 июн 2026, 11:55
Не верифицирован
24 июн 2026, 11:55
cacb7d0
Код
Авторство
О чём код?
import { Binary } from "@opencode-ai/core/util/binary" import { createMemo } from "solid-js" import { useServerSync } from "./server-sync" import { useSDK } from "./sdk" import type { Message, Part } from "@opencode-ai/sdk/v2/client" const SKIP_PARTS = new Set(["patch", "step-start", "step-finish"]) function sortParts(parts: Part[]) { return parts.filter((part) => !!part?.id).sort((a, b) => cmp(a.id, b.id)) } const cmp = (a: string, b: string) => (a < b ? -1 : a > b ? 1 : 0) type OptimisticStore = { message: Record<string, Message[] | undefined> part: Record<string, Part[] | undefined> } type OptimisticAddInput = { sessionID: string message: Message parts: Part[] } type OptimisticRemoveInput = { sessionID: string messageID: string } type OptimisticItem = { message: Message parts: Part[] } type MessagePage = { session: Message[] part: { id: string; part: Part[] }[] cursor?: string complete: boolean } const hasParts = (parts: Part[] | undefined, want: Part[]) => { if (!parts) return want.length === 0 return want.every((part) => Binary.search(parts, part.id, (item) => item.id).found) } const mergeParts = (parts: Part[] | undefined, want: Part[]) => { if (!parts) return sortParts(want) const next = [...parts] let changed = false for (const part of want) { const result = Binary.search(next, part.id, (item) => item.id) if (result.found) continue next.splice(result.index, 0, part) changed = true } if (!changed) return parts return next } export function mergeOptimisticPage(page: MessagePage, items: OptimisticItem[]) { if (items.length === 0) return { ...page, confirmed: [] as string[] } const session = [...page.session] const part = new Map(page.part.map((item) => [item.id, sortParts(item.part)])) const confirmed: string[] = [] for (const item of items) { const result = Binary.search(session, item.message.id, (message) => message.id) const found = result.found if (!found) session.splice(result.index, 0, item.message) const current = part.get(item.message.id) if (found && hasParts(current, item.parts)) { confirmed.push(item.message.id) continue } part.set(item.message.id, mergeParts(current, item.parts)) } return { cursor: page.cursor, complete: page.complete, session, part: [...part.entries()].sort((a, b) => cmp(a[0], b[0])).map(([id, part]) => ({ id, part })), confirmed, } } export function applyOptimisticAdd(draft: OptimisticStore, input: OptimisticAddInput) { const messages = draft.message[input.sessionID] if (messages) { const result = Binary.search(messages, input.message.id, (m) => m.id) messages.splice(result.index, 0, input.message) } else { draft.message[input.sessionID] = [input.message] } draft.part[input.message.id] = sortParts(input.parts) } export function applyOptimisticRemove(draft: OptimisticStore, input: OptimisticRemoveInput) { const messages = draft.message[input.sessionID] if (messages) { const result = Binary.search(messages, input.messageID, (m) => m.id) if (result.found) messages.splice(result.index, 1) } delete draft.part[input.messageID] } export const useSync = () => { const serverSync = useServerSync() const sdk = useSDK() return createMemo(() => serverSync().ensureDirSyncContext(sdk().directory)) } export type DirectorySync = ReturnType<ReturnType<typeof useSync>>