chore: generate

This commit is contained in:
opencode-agent[bot] 2026-06-16 16:57:04 +00:00
commit 273efdeee7
11 changed files with 427 additions and 405 deletions

View file

@ -196,7 +196,8 @@ test.describe("regression: session timeline local row state", () => {
const events: EventPayload[] = []
const lines = Array.from({ length: 1_000 }, (_, index) => `export const value${index} = ${index}\n`).join("")
const after = [100, 300, 500, 700, 900].reduce(
(result, index) => result.replace(`export const value${index} = ${index}`, `export const value${index} = compute(${index})`),
(result, index) =>
result.replace(`export const value${index} = ${index}`, `export const value${index} = compute(${index})`),
lines,
)
const part = {
@ -385,11 +386,7 @@ function readExpanded(element: Element) {
return !!content && content.getBoundingClientRect().height > 0
}
async function mockServer(
page: Page,
events: EventPayload[],
messages = [userMessage, assistantMessage],
) {
async function mockServer(page: Page, events: EventPayload[], messages = [userMessage, assistantMessage]) {
await mockOpenCodeServer(page, {
directory,
project: project(),

View file

@ -172,7 +172,9 @@ test.describe("smoke: session timeline", () => {
})
.map((element) => element.dataset.messageId!)
.filter((id) => ids.has(id))
const bottom = root.querySelector<HTMLElement>('[data-timeline-row="bottom-spacer"]')?.getBoundingClientRect()
const bottom = root
.querySelector<HTMLElement>('[data-timeline-row="bottom-spacer"]')
?.getBoundingClientRect()
samples.push({ ids: visible, last: visible.includes(last), bottomError: bottom?.bottom - view.bottom })
if (!firstPaint && visible.includes(last) && Math.abs((bottom?.bottom ?? Infinity) - view.bottom) <= 1) {
firstPaint = true
@ -187,9 +189,11 @@ test.describe("smoke: session timeline", () => {
requestAnimationFrame(sample)
}, 0)
}
;(window as Window & {
__sessionTabPaint?: { samples: typeof samples; removed: () => number; stop: () => void }
}).__sessionTabPaint = {
;(
window as Window & {
__sessionTabPaint?: { samples: typeof samples; removed: () => number; stop: () => void }
}
).__sessionTabPaint = {
samples,
removed: () => removedFirstPaintNodes,
stop: () => {
@ -203,19 +207,21 @@ test.describe("smoke: session timeline", () => {
await switchTitlebarSession(page, fixture.targetID, fixture.expected.targetTitle)
await page.waitForFunction(() =>
(window as Window & { __sessionTabPaint?: { samples: Array<{ ids: string[] }> } }).__sessionTabPaint?.samples.some(
(sample) => sample.ids.length > 0,
),
(
window as Window & { __sessionTabPaint?: { samples: Array<{ ids: string[] }> } }
).__sessionTabPaint?.samples.some((sample) => sample.ids.length > 0),
)
await page.waitForTimeout(200)
const first = await page.evaluate(() => {
const probe = (window as Window & {
__sessionTabPaint?: {
samples: Array<{ ids: string[]; last: boolean; bottomError?: number }>
removed: () => number
stop: () => void
const probe = (
window as Window & {
__sessionTabPaint?: {
samples: Array<{ ids: string[]; last: boolean; bottomError?: number }>
removed: () => number
stop: () => void
}
}
}).__sessionTabPaint!
).__sessionTabPaint!
probe.stop()
return { first: probe.samples.find((sample) => sample.ids.length > 0), removed: probe.removed() }
})
@ -253,31 +259,36 @@ test.describe("smoke: session timeline", () => {
await expectSessionTitle(page, fixture.expected.sourceTitle)
const last = fixture.expected.targetMessageIDs.at(-1)!
const destination = fixture.messages[fixture.targetID].map((message) => message.info.id)
await page.evaluate(({ destination, last }) => {
const ids = new Set(destination)
const samples: Array<{ destination: boolean; last: boolean; bottomError?: number }> = []
const sample = () => {
const root = [...document.querySelectorAll<HTMLElement>(".scroll-view__viewport")].find((element) =>
element.querySelector("[data-timeline-row]"),
)
if (root) {
const view = root.getBoundingClientRect()
const spacer = root.querySelector<HTMLElement>('[data-timeline-row="bottom-spacer"]')?.getBoundingClientRect()
const messages = [...root.querySelectorAll<HTMLElement>("[data-message-id]")].filter((element) => {
const rect = element.getBoundingClientRect()
return rect.bottom > view.top && rect.top < view.bottom
})
samples.push({
destination: messages.some((element) => ids.has(element.dataset.messageId!)),
last: messages.some((element) => element.dataset.messageId === last),
bottomError: spacer ? spacer.bottom - view.bottom : undefined,
})
await page.evaluate(
({ destination, last }) => {
const ids = new Set(destination)
const samples: Array<{ destination: boolean; last: boolean; bottomError?: number }> = []
const sample = () => {
const root = [...document.querySelectorAll<HTMLElement>(".scroll-view__viewport")].find((element) =>
element.querySelector("[data-timeline-row]"),
)
if (root) {
const view = root.getBoundingClientRect()
const spacer = root
.querySelector<HTMLElement>('[data-timeline-row="bottom-spacer"]')
?.getBoundingClientRect()
const messages = [...root.querySelectorAll<HTMLElement>("[data-message-id]")].filter((element) => {
const rect = element.getBoundingClientRect()
return rect.bottom > view.top && rect.top < view.bottom
})
samples.push({
destination: messages.some((element) => ids.has(element.dataset.messageId!)),
last: messages.some((element) => element.dataset.messageId === last),
bottomError: spacer ? spacer.bottom - view.bottom : undefined,
})
}
requestAnimationFrame(() => setTimeout(sample, 0))
}
;(window as Window & { __coldTabSamples?: typeof samples }).__coldTabSamples = samples
requestAnimationFrame(() => setTimeout(sample, 0))
}
;(window as Window & { __coldTabSamples?: typeof samples }).__coldTabSamples = samples
requestAnimationFrame(() => setTimeout(sample, 0))
}, { destination, last })
},
{ destination, last },
)
await switchTitlebarSession(page, fixture.targetID, fixture.expected.targetTitle)
await page.waitForFunction(() =>
@ -286,9 +297,11 @@ test.describe("smoke: session timeline", () => {
),
)
const result = await page.evaluate(() => {
const samples = (window as Window & {
__coldTabSamples?: Array<{ destination: boolean; last: boolean; bottomError?: number }>
}).__coldTabSamples!
const samples = (
window as Window & {
__coldTabSamples?: Array<{ destination: boolean; last: boolean; bottomError?: number }>
}
).__coldTabSamples!
return samples.find((sample) => sample.destination)!
})
expect(result.last).toBe(true)

View file

@ -82,10 +82,7 @@ type FramedTimelineRow = Exclude<TimelineRow.TimelineRow, { _tag: "TurnGap" }>
type TimelineRowByTag<T extends TimelineRow.TimelineRow["_tag"]> = Extract<TimelineRow.TimelineRow, { _tag: T }>
const timelineFallbackItemSize = 60
const timelineCache = new Map<
string,
{ measurements: VirtualItem[]; toolOpen: Record<string, boolean | undefined> }
>()
const timelineCache = new Map<string, { measurements: VirtualItem[]; toolOpen: Record<string, boolean | undefined> }>()
const taskDescription = (part: PartType, sessionID: string) => {
if (part.type !== "tool" || part.tool !== "task") return

View file

@ -55,11 +55,7 @@ export function createTimelineModel(input: {
const id = input.sessionID()
return !id || sync().data.message[id] !== undefined
})
const userMessages = createMemo(
() => selectUserMessages(messages()),
emptyUserMessages,
{ equals: same },
)
const userMessages = createMemo(() => selectUserMessages(messages()), emptyUserMessages, { equals: same })
const visibleUserMessages = createMemo(
() => {
return selectVisibleUserMessages(userMessages(), input.revertMessageID())

View file

@ -27,9 +27,12 @@ export function createTimelineProjection(input: {
return result
})
const activeMessageID = createMemo(() => {
const parentID = input.messages().findLast(
(message): message is AssistantMessage => message.role === "assistant" && typeof message.time.completed !== "number",
)?.parentID
const parentID = input
.messages()
.findLast(
(message): message is AssistantMessage =>
message.role === "assistant" && typeof message.time.completed !== "number",
)?.parentID
if (parentID) {
const messages = input.messages()
const result = Binary.search(messages, parentID, (message) => message.id)