chore: generate
This commit is contained in:
parent
3b811bd019
commit
273efdeee7
11 changed files with 427 additions and 405 deletions
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue