fix(app): update remote sdk contracts

This commit is contained in:
Dax Raad 2026-07-26 20:15:43 -04:00
parent 8db7487c89
commit 5592f5225b
20 changed files with 62 additions and 51 deletions

View file

@ -8,8 +8,8 @@ import type {
QuestionRequest,
Session,
SessionStatus,
FileDiffInfo,
} from "@opencode-ai/sdk/v2/client"
import type { SessionDiff } from "@/utils/diffs"
import type { State, VcsCache } from "./types"
import { trimSessions } from "./session-trim"
import { dropSessionCaches } from "./session-cache"
@ -171,7 +171,7 @@ export function applyDirectoryEvent(input: {
break
}
case "session.diff": {
const props = event.properties as { sessionID: string; diff: FileDiffInfo[] }
const props = event.properties as { sessionID: string; diff: SessionDiff[] }
input.setStore("session_diff", props.sessionID, reconcile(list(props.diff), { key: "file" }))
break
}

View file

@ -5,8 +5,8 @@ import type {
PermissionRequest,
QuestionRequest,
SessionStatus,
FileDiffInfo,
} from "@opencode-ai/sdk/v2/client"
import type { SessionDiff } from "@/utils/diffs"
import { dropSessionCaches, pickSessionCacheEvictions } from "./session-cache"
const msg = (id: string, sessionID: string) =>
@ -32,7 +32,7 @@ describe("app session cache", () => {
test("dropSessionCaches clears orphaned parts without message rows", () => {
const store: {
session_status: Record<string, SessionStatus | undefined>
session_diff: Record<string, FileDiffInfo[] | undefined>
session_diff: Record<string, SessionDiff[] | undefined>
message: Record<string, Message[] | undefined>
part: Record<string, Part[] | undefined>
permission: Record<string, PermissionRequest[] | undefined>
@ -63,7 +63,7 @@ describe("app session cache", () => {
const m = msg("msg_1", "ses_1")
const store: {
session_status: Record<string, SessionStatus | undefined>
session_diff: Record<string, FileDiffInfo[] | undefined>
session_diff: Record<string, SessionDiff[] | undefined>
message: Record<string, Message[] | undefined>
part: Record<string, Part[] | undefined>
permission: Record<string, PermissionRequest[] | undefined>

View file

@ -4,14 +4,14 @@ import type {
PermissionRequest,
QuestionRequest,
SessionStatus,
FileDiffInfo,
} from "@opencode-ai/sdk/v2/client"
import type { SessionDiff } from "@/utils/diffs"
export const SESSION_CACHE_LIMIT = 40
type SessionCache = {
session_status: Record<string, SessionStatus | undefined>
session_diff: Record<string, FileDiffInfo[] | undefined>
session_diff: Record<string, SessionDiff[] | undefined>
message: Record<string, Message[] | undefined>
part: Record<string, Part[] | undefined>
permission: Record<string, PermissionRequest[] | undefined>

View file

@ -13,9 +13,9 @@ import type {
ReferenceInfo,
Session,
SessionStatus,
FileDiffInfo,
VcsInfo,
} from "@opencode-ai/sdk/v2/client"
import type { SessionDiff } from "@/utils/diffs"
import { NormalizedProviderListResponse } from "@opencode-ai/session-ui/context"
import type { Accessor } from "solid-js"
import type { SetStoreFunction, Store } from "solid-js/store"
@ -50,7 +50,7 @@ export type State = {
}
session_working(id: string): boolean
session_diff: {
[sessionID: string]: FileDiffInfo[]
[sessionID: string]: SessionDiff[]
}
permission: {
[sessionID: string]: PermissionRequest[]

View file

@ -1,5 +1,5 @@
import type { OpenCodeEvent } from "@opencode-ai/client/promise"
import type { Event } from "@opencode-ai/sdk/v2/client"
import type { Event, PermissionRequest } from "@opencode-ai/sdk/v2/client"
import { createSimpleContext } from "@opencode-ai/ui/context"
import { createGlobalEmitter } from "@solid-primitives/event-bus"
import { makeEventListener } from "@solid-primitives/event-listener"
@ -18,7 +18,15 @@ const isAbortError = (error: unknown) =>
error !== null && typeof error === "object" && "name" in error && error.name === "AbortError"
const isStreamClosed = (error: unknown, signal?: AbortSignal) => isAbortError(error) || signal?.aborted === true
export type ServerEvent = Event & { current?: OpenCodeEvent }
type PermissionEvent = {
id: string
type: "permission.v2.asked"
properties: PermissionRequest
current?: OpenCodeEvent
}
export type ServerEvent = (Event | PermissionEvent) & {
current?: OpenCodeEvent
}
type QueuedServerEvent = { directory: string; payload: ServerEvent }
type CurrentDelta = Extract<
OpenCodeEvent,
@ -43,7 +51,7 @@ export function adaptServerEvent(event: OpenCodeEvent): ServerEvent {
: undefined,
},
current: event,
} as ServerEvent
}
}
if (event.type === "permission.v2.replied")
return { id: event.id, type: "permission.v2.replied", properties: event.data, current: event } as ServerEvent

View file

@ -8,8 +8,8 @@ import type {
QuestionRequest,
Session,
SessionStatus,
FileDiffInfo,
} from "@opencode-ai/sdk/v2/client"
import type { SessionDiff } from "@/utils/diffs"
import { batch } from "solid-js"
import { createStore, produce, reconcile } from "solid-js/store"
import { diffs as cleanDiffs, message as cleanMessage } from "@/utils/diffs"
@ -140,7 +140,7 @@ export function createServerSession(client: OpencodeClient, options?: { retry?:
const [data, setData] = createStore({
info: {} as Record<string, Session | undefined>,
session_status: {} as Record<string, SessionStatus>,
session_diff: {} as Record<string, FileDiffInfo[]>,
session_diff: {} as Record<string, SessionDiff[]>,
permission: {} as Record<string, PermissionRequest[]>,
question: {} as Record<string, QuestionRequest[]>,
message: {} as Record<string, Message[]>,
@ -773,7 +773,7 @@ export function createServerSession(client: OpencodeClient, options?: { retry?:
return
}
case "session.diff": {
const props = event.properties as { sessionID: string; diff: FileDiffInfo[] }
const props = event.properties as { sessionID: string; diff: SessionDiff[] }
setData("session_diff", props.sessionID, reconcile(cleanDiffs(props.diff), { key: "file" }))
return
}

View file

@ -909,13 +909,8 @@ export default function Page() {
)
const stopVcs = sdk().event.listen((evt) => {
if (evt.details.type !== "filesystem.changed") return
const props =
typeof evt.details.properties === "object" && evt.details.properties
? (evt.details.properties as Record<string, unknown>)
: undefined
const file = typeof props?.file === "string" ? props.file : undefined
if (!file || file.startsWith(".git/")) return
if (evt.details.type !== "file.watcher.updated") return
if (evt.details.properties.file.startsWith(".git/")) return
refreshVcs()
})
onCleanup(stopVcs)

View file

@ -1,6 +1,7 @@
import { createEffect, onCleanup, type JSX } from "solid-js"
import { makeEventListener } from "@solid-primitives/event-listener"
import type { FileDiffInfo, VcsFileDiff } from "@opencode-ai/sdk/v2"
import type { VcsFileDiff } from "@opencode-ai/sdk/v2"
import type { SessionDiff } from "@/utils/diffs"
import { SessionReview } from "@opencode-ai/session-ui/session-review"
import type {
SessionReviewCommentActions,
@ -14,7 +15,7 @@ import type { LineComment } from "@/context/comments"
export type DiffStyle = "unified" | "split"
type ReviewDiff = FileDiffInfo | VcsFileDiff
type ReviewDiff = SessionDiff | VcsFileDiff
export interface SessionReviewTabProps {
title?: JSX.Element

View file

@ -23,7 +23,8 @@ import { Mark } from "@opencode-ai/ui/logo"
import { IconButtonV2 } from "@opencode-ai/ui/v2/icon-button-v2"
import { KeybindV2 } from "@opencode-ai/ui/v2/keybind-v2"
import { TooltipV2 } from "@opencode-ai/ui/v2/tooltip-v2"
import type { FileDiffInfo, VcsFileDiff } from "@opencode-ai/sdk/v2"
import type { VcsFileDiff } from "@opencode-ai/sdk/v2"
import type { SessionDiff } from "@/utils/diffs"
import { ConstrainDragYAxis, getDraggableId } from "@/utils/solid-dnd"
import { useDialog } from "@opencode-ai/ui/context/dialog"
@ -59,7 +60,7 @@ import type { RenderDiff } from "@/pages/session/v2/review-diff-kinds"
export function SessionSidePanel(props: {
canReview: () => boolean
diffs: () => (FileDiffInfo | VcsFileDiff)[]
diffs: () => (SessionDiff | VcsFileDiff)[]
diffsReady: () => boolean
empty: () => string
hasReview: () => boolean

View file

@ -1,8 +1,9 @@
import type { FileDiffInfo, VcsFileDiff } from "@opencode-ai/sdk/v2"
import type { VcsFileDiff } from "@opencode-ai/sdk/v2"
import type { SessionDiff } from "@/utils/diffs"
import type { Kind } from "@/components/file-tree-v2"
import { normalizeFileTreeV2Path } from "@/components/file-tree-v2-model"
export type RenderDiff = FileDiffInfo | VcsFileDiff
export type RenderDiff = SessionDiff | VcsFileDiff
export function normalizePath(p: string) {
return normalizeFileTreeV2Path(p)

View file

@ -1,5 +1,6 @@
import { createMemo, createResource, createSignal, Show, type JSX } from "solid-js"
import type { FileDiffInfo, VcsFileDiff } from "@opencode-ai/sdk/v2"
import type { VcsFileDiff } from "@opencode-ai/sdk/v2"
import type { SessionDiff } from "@/utils/diffs"
import {
SESSION_REVIEW_V2_SIDEBAR_WIDTH_MAX,
SESSION_REVIEW_V2_SIDEBAR_WIDTH_MIN,
@ -29,7 +30,7 @@ import {
import type { ReviewPanelV2State } from "@/pages/session/v2/review-panel-v2-state"
import { applyFileListKeyDown, SessionFileListV2 } from "@/pages/session/v2/session-file-list-v2"
type ReviewDiff = FileDiffInfo | VcsFileDiff
type ReviewDiff = SessionDiff | VcsFileDiff
export type ReviewPanelV2Props = {
title?: JSX.Element

View file

@ -1,5 +1,5 @@
import { describe, expect, test } from "bun:test"
import type { FileDiffInfo } from "@opencode-ai/sdk/v2"
import type { SnapshotFileDiff } from "@opencode-ai/sdk/v2"
import type { Message } from "@opencode-ai/sdk/v2/client"
import { diffs, message } from "./diffs"
@ -9,7 +9,7 @@ const item = {
additions: 1,
deletions: 1,
status: "modified",
} satisfies FileDiffInfo
} satisfies SnapshotFileDiff
describe("diffs", () => {
test("keeps valid arrays", () => {

View file

@ -1,9 +1,9 @@
import type { FileDiffInfo } from "@opencode-ai/sdk/v2"
import type { SnapshotFileDiff } from "@opencode-ai/sdk/v2"
import type { Message } from "@opencode-ai/sdk/v2/client"
type Diff = FileDiffInfo
export type SessionDiff = SnapshotFileDiff & { file: string; patch: string }
function diff(value: unknown): value is Diff {
function diff(value: unknown): value is SessionDiff {
if (!value || typeof value !== "object" || Array.isArray(value)) return false
if (!("file" in value) || typeof value.file !== "string") return false
if (!("patch" in value) || typeof value.patch !== "string") return false
@ -17,7 +17,7 @@ function object(value: unknown): value is Record<string, unknown> {
return !!value && typeof value === "object" && !Array.isArray(value)
}
export function diffs(value: unknown): Diff[] {
export function diffs(value: unknown): SessionDiff[] {
if (Array.isArray(value) && value.every(diff)) return value
if (Array.isArray(value)) return value.filter(diff)
if (diff(value)) return [value]

View file

@ -1,4 +1,4 @@
import { FileDiffInfo, Message, Model, Part, Session } from "@opencode-ai/sdk/v2"
import { Message, Model, Part, Session, SnapshotFileDiff } from "@opencode-ai/sdk/v2"
import { iife } from "@opencode-ai/core/util/iife"
import z from "zod"
import { Storage } from "./storage"
@ -8,6 +8,8 @@ function fn<T extends z.ZodType, Result>(schema: T, cb: (input: z.infer<T>) => R
}
export namespace Share {
export type SessionDiff = SnapshotFileDiff & { file: string; patch: string }
export const Info = z.object({
id: z.string(),
secret: z.string(),
@ -30,7 +32,7 @@ export namespace Share {
}),
z.object({
type: z.literal("session_diff"),
data: z.custom<FileDiffInfo[]>(),
data: z.custom<SessionDiff[]>(),
}),
z.object({
type: z.literal("model"),

View file

@ -1,4 +1,4 @@
import { FileDiffInfo, Message, Model, Part, Session, SessionStatus, UserMessage } from "@opencode-ai/sdk/v2"
import { Message, Model, Part, Session, SessionStatus, UserMessage } from "@opencode-ai/sdk/v2"
import { SessionTurn } from "@opencode-ai/session-ui/session-turn"
import { SessionReview } from "@opencode-ai/session-ui/session-review"
import { DataProvider } from "@opencode-ai/session-ui/context"
@ -65,7 +65,7 @@ const getData = query(async (shareID) => {
shareID: string
session: Session[]
session_diff: {
[sessionID: string]: FileDiffInfo[]
[sessionID: string]: Share.SessionDiff[]
}
session_status: {
[sessionID: string]: SessionStatus

View file

@ -1,6 +1,6 @@
import { parseDiffFromFile, parsePatchFiles, type FileDiffMetadata } from "@pierre/diffs"
import { parsePatch } from "diff"
import type { FileDiffInfo, VcsFileDiff } from "@opencode-ai/sdk/v2"
import type { SnapshotFileDiff, VcsFileDiff } from "@opencode-ai/sdk/v2"
type LegacyDiff = {
file: string
@ -12,7 +12,7 @@ type LegacyDiff = {
status?: "added" | "deleted" | "modified"
}
type ReviewDiff = FileDiffInfo | VcsFileDiff | LegacyDiff
type ReviewDiff = (SnapshotFileDiff | VcsFileDiff | LegacyDiff) & { file: string }
export type DiffSource = Pick<LegacyDiff, "file" | "patch" | "before" | "after">
export type ViewDiff = {

View file

@ -15,7 +15,7 @@ import { getDirectory, getFilename } from "@opencode-ai/core/util/path"
import { checksum } from "@opencode-ai/core/util/encode"
import { createEffect, createMemo, For, Match, onCleanup, Show, Switch, untrack, type JSX } from "solid-js"
import { createStore } from "solid-js/store"
import { type FileContent, type FileDiffInfo, type VcsFileDiff } from "@opencode-ai/sdk/v2"
import { type FileContent, type SnapshotFileDiff, type VcsFileDiff } from "@opencode-ai/sdk/v2"
import { PreloadMultiFileDiffResult } from "@pierre/diffs/ssr"
import { type SelectedLineRange } from "@pierre/diffs"
import { Dynamic } from "solid-js/web"
@ -62,10 +62,12 @@ export type SessionReviewCommentActions = {
export type SessionReviewFocus = { file: string; id: string }
type RawReviewDiff = (FileDiffInfo | VcsFileDiff) & {
type RawReviewDiff = (SnapshotFileDiff | VcsFileDiff) & {
file: string
preloaded?: PreloadMultiFileDiffResult<any>
}
type ReviewDiff = (FileDiffInfo | VcsFileDiff) & {
type ReviewDiff = (SnapshotFileDiff | VcsFileDiff) & {
file: string
preloaded?: PreloadMultiFileDiffResult<any>
}
function diff(value: unknown): value is ReviewDiff {

View file

@ -1,6 +1,6 @@
import {
AssistantMessage,
type FileDiffInfo,
type SnapshotFileDiff,
Message as MessageType,
Part as PartType,
type UserMessage,
@ -92,7 +92,7 @@ function list<T>(value: T[] | undefined | null, fallback: T[]) {
}
type SummaryDiffInput = NonNullable<NonNullable<UserMessage["summary"]>["diffs"]>[number]
type SummaryDiff = FileDiffInfo
type SummaryDiff = SnapshotFileDiff & { file: string; patch: string }
function summaryDiff(value: SummaryDiffInput): value is SummaryDiff {
return (

View file

@ -1,4 +1,4 @@
import type { FileDiffInfo, Message, Part, Provider, Session, SessionStatus } from "@opencode-ai/sdk/v2"
import type { Message, Part, Provider, Session, SessionStatus, SnapshotFileDiff } from "@opencode-ai/sdk/v2"
import { createSimpleContext } from "@opencode-ai/ui/context"
import { PreloadMultiFileDiffResult } from "@pierre/diffs/ssr"
@ -21,7 +21,7 @@ type Data = {
[sessionID: string]: SessionStatus
}
session_diff: {
[sessionID: string]: FileDiffInfo[]
[sessionID: string]: SnapshotFileDiff[]
}
session_diff_preload?: {
[sessionID: string]: PreloadMultiFileDiffResult<any>[]

View file

@ -6,7 +6,7 @@ import { useFileComponent } from "@opencode-ai/ui/context/file"
import { useI18n } from "@opencode-ai/ui/context/i18n"
import { mediaKindFromPath } from "../../pierre/media"
import { cloneSelectedLineRange, previewSelectedLines } from "../../pierre/selection-bridge"
import type { FileContent, FileDiffInfo, VcsFileDiff } from "@opencode-ai/sdk/v2"
import type { FileContent, SnapshotFileDiff, VcsFileDiff } from "@opencode-ai/sdk/v2"
import { createEffect, createMemo, onCleanup, Show, untrack } from "solid-js"
import { createStore } from "solid-js/store"
import { Dynamic } from "solid-js/web"
@ -27,7 +27,7 @@ import { LineCommentV2OverflowIcon } from "@opencode-ai/ui/v2/line-comment-v2"
import { MenuV2 } from "@opencode-ai/ui/v2/menu-v2"
import "./session-review-v2.css"
type ReviewDiff = FileDiffInfo | VcsFileDiff
type ReviewDiff = (SnapshotFileDiff | VcsFileDiff) & { file: string }
export type SessionReviewFilePreviewV2Props = {
file: string