Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
022ed7e
test(app): migrate e2e fixtures to v2
Brendonovich Aug 4, 2026
2564e6c
refactor(app): own rendering contracts
Brendonovich Aug 4, 2026
3c6e19d
fix(app): reconcile v2 session projections
Brendonovich Aug 4, 2026
ca00e39
refactor(app): migrate supported v2 APIs
Brendonovich Aug 4, 2026
8bd5407
refactor(app): gate unsupported v2 capabilities
Brendonovich Aug 4, 2026
1ce2ca5
refactor(app): remove v1 compatibility
Brendonovich Aug 4, 2026
4e1fc3e
test(app): keep e2e mocks stack-compatible
Brendonovich Aug 4, 2026
2ce6c31
Merge branch 'app-v2-e2e' into app-rendering-types
Brendonovich Aug 4, 2026
5f3327a
Merge branch 'app-rendering-types' into app-v2-sessions
Brendonovich Aug 4, 2026
36c8789
test(app): update v2 history root fixture
Brendonovich Aug 4, 2026
251d26a
Merge branch 'app-v2-sessions' into app-v2-apis
Brendonovich Aug 4, 2026
e0285d3
test(app): cover migrated v2 operations
Brendonovich Aug 4, 2026
0be919b
Merge branch 'app-v2-apis' into app-v2-gating
Brendonovich Aug 4, 2026
799b05f
Merge branch 'app-v2-gating' into app-v1-removal
Brendonovich Aug 4, 2026
023ccbd
test(app): finalize v2-only e2e expectations
Brendonovich Aug 4, 2026
5deafd9
test(app): align migrated session projections
Brendonovich Aug 4, 2026
65ba003
Merge branch 'app-v2-apis' into app-v2-gating
Brendonovich Aug 4, 2026
fe40151
Merge branch 'app-v2-gating' into app-v1-removal
Brendonovich Aug 4, 2026
84787ec
test(app): select v2 smoke transport
Brendonovich Aug 4, 2026
38df0b0
Merge branch 'app-v2-apis' into app-v2-gating
Brendonovich Aug 4, 2026
be9d49c
test(app): retain gated legacy projection coverage
Brendonovich Aug 4, 2026
8235fe6
Merge branch 'app-v2-gating' into app-v1-removal
Brendonovich Aug 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

220 changes: 0 additions & 220 deletions packages/app/V1_API_MIGRATION.md

This file was deleted.

53 changes: 27 additions & 26 deletions packages/app/e2e/performance/timeline-stability/fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,8 @@ import { base64Encode } from "@opencode-ai/core/util/encode"
import { Event } from "@opencode-ai/schema/event"
import { SessionStatusEvent } from "@opencode-ai/schema/session-status-event"
import { SessionV1 } from "@opencode-ai/schema/session-v1"
import type {
AssistantMessage,
GlobalEvent,
Message,
Part,
Session,
SessionStatus,
ToolPart,
ToolState,
UserMessage,
} from "@opencode-ai/sdk/v2/client"
import type { SessionV1Info, SessionStatus } from "@opencode-ai/client/promise"
import type { AssistantMessage, Message, Part, ToolPart, ToolState, UserMessage } from "../../../src/types"
import { expect, type Page } from "@playwright/test"
import { Schema } from "effect"
import { mockOpenCodeServer } from "../../utils/mock-server"
Expand All @@ -27,18 +18,29 @@ export const assistantID = "msg_1001_timeline_assistant"
export const title = "Timeline visual stability"
export const model = { providerID: "opencode", modelID: "claude-opus-4-6", variant: "max" }

type TimelinePayload = Extract<
GlobalEvent["payload"],
{
type:
| "message.updated"
| "message.removed"
| "message.part.updated"
| "message.part.removed"
| "message.part.delta"
| "session.status"
type Session = SessionV1Info
type GlobalEvent = {
directory: string
project?: string
workspace?: string
payload: {
id: string
type: string
properties: Record<string, unknown>
}
>
}

type TimelineProperties = {
"message.updated": { sessionID: string; info: Message }
"message.removed": { sessionID: string; messageID: string }
"message.part.updated": { sessionID: string; part: Part; time: number }
"message.part.removed": { sessionID: string; messageID: string; partID: string }
"message.part.delta": { sessionID: string; messageID: string; partID: string; field: string; delta: string }
"session.status": { sessionID: string; status: SessionStatus }
}
type TimelinePayload = {
[Type in keyof TimelineProperties]: { id: string; type: Type; properties: TimelineProperties[Type] }
}[keyof TimelineProperties]

type DeepReadonly<Value> = Value extends readonly unknown[]
? { readonly [Key in keyof Value]: DeepReadonly<Value[Key]> }
Expand Down Expand Up @@ -97,7 +99,6 @@ export async function setupTimeline(
locale?: string
deviceScaleFactor?: number
seedHistory?: boolean
protocol?: "v1" | "v2"
} = {},
) {
const sessions = input.sessions ?? [session()]
Expand All @@ -115,7 +116,7 @@ export async function setupTimeline(
retry: input.eventRetry ?? 20,
})
await mockOpenCodeServer(page, {
protocol: input.protocol,
protocol: "v2",
directory,
project: project(),
provider: provider(),
Expand Down Expand Up @@ -235,7 +236,7 @@ export function event(type: TimelinePayload["type"], properties: TimelinePayload
}

export function validateTimelineEvent(input: unknown): TimelineEvent {
return decodeEvent(input, decodeOptions)
return decodeEvent(input, decodeOptions) as TimelineEvent
}

export function validateTimelineMessages(input: readonly TimelineMessage[]): TimelineMessage[] {
Expand Down Expand Up @@ -460,7 +461,7 @@ export function toolPart(
input: Record<string, unknown>,
options: ToolOptions<ToolStatus> = {},
): Omit<ToolPart, "sessionID" | "messageID"> {
const base = { id, type: "tool" as const, callID: `call_${id}`, tool }
const base = { id, type: "tool" as const, callID: id, tool }
if (state === "pending") return { ...base, state: { status: state, input, raw: "" } }
if (state === "running")
return {
Expand Down
Loading
Loading