From b04f7242e6734935d733abaa7c73fc4980f73ac0 Mon Sep 17 00:00:00 2001 From: Le Vivilet Date: Sun, 10 May 2026 19:41:17 +0000 Subject: [PATCH 1/3] feat: Implement createDevtoolsRows function and associated tests for row state management --- .../CreateDevtoolsRows/CreateDevtoolsRows.ts | 16 +++++ .../src/parts/DevtoolsRow/DevtoolsRow.ts | 9 +++ .../parts/GetDevtoolsDom/GetDevtoolsDom.ts | 4 +- .../parts/GetDevtoolsRows/GetDevtoolsRows.ts | 21 ++---- .../test/CreateDevtoolsRows.test.ts | 68 +++++++++++++++++++ .../test/GetDevtoolsRows.test.ts | 31 ++++++--- 6 files changed, 126 insertions(+), 23 deletions(-) create mode 100644 packages/chat-debug-view/src/parts/CreateDevtoolsRows/CreateDevtoolsRows.ts create mode 100644 packages/chat-debug-view/src/parts/DevtoolsRow/DevtoolsRow.ts create mode 100644 packages/chat-debug-view/test/CreateDevtoolsRows.test.ts diff --git a/packages/chat-debug-view/src/parts/CreateDevtoolsRows/CreateDevtoolsRows.ts b/packages/chat-debug-view/src/parts/CreateDevtoolsRows/CreateDevtoolsRows.ts new file mode 100644 index 00000000..33bb84e6 --- /dev/null +++ b/packages/chat-debug-view/src/parts/CreateDevtoolsRows/CreateDevtoolsRows.ts @@ -0,0 +1,16 @@ +import type { ChatViewEvent } from '../ChatViewEvent/ChatViewEvent.ts' +import type { DevtoolsRow } from '../DevtoolsRow/DevtoolsRow.ts' +import { hasErrorStatus } from '../HasErrorStatus/HasErrorStatus.ts' + +export const createDevtoolsRows = (events: readonly ChatViewEvent[], selectedEventIndex: number | null, startIndex = 0): readonly DevtoolsRow[] => { + return events.map((event, index) => { + const actualIndex = startIndex + index + return { + event, + index: actualIndex, + isErrorStatus: hasErrorStatus(event), + isEven: actualIndex % 2 === 1, + isSelected: selectedEventIndex === actualIndex, + } + }) +} diff --git a/packages/chat-debug-view/src/parts/DevtoolsRow/DevtoolsRow.ts b/packages/chat-debug-view/src/parts/DevtoolsRow/DevtoolsRow.ts new file mode 100644 index 00000000..08ac2798 --- /dev/null +++ b/packages/chat-debug-view/src/parts/DevtoolsRow/DevtoolsRow.ts @@ -0,0 +1,9 @@ +import type { ChatViewEvent } from '../ChatViewEvent/ChatViewEvent.ts' + +export interface DevtoolsRow { + readonly event: ChatViewEvent + readonly index: number + readonly isErrorStatus: boolean + readonly isEven: boolean + readonly isSelected: boolean +} diff --git a/packages/chat-debug-view/src/parts/GetDevtoolsDom/GetDevtoolsDom.ts b/packages/chat-debug-view/src/parts/GetDevtoolsDom/GetDevtoolsDom.ts index f952fe21..255a9881 100644 --- a/packages/chat-debug-view/src/parts/GetDevtoolsDom/GetDevtoolsDom.ts +++ b/packages/chat-debug-view/src/parts/GetDevtoolsDom/GetDevtoolsDom.ts @@ -4,6 +4,7 @@ import type { DetailTab as DetailTabType } from '../DetailTab/DetailTab.ts' import type { TimelineInfo } from '../GetTimelineInfo/GetTimelineInfo.ts' import * as ChatDebugStrings from '../ChatDebugStrings/ChatDebugStrings.ts' import { ChatDebugView, ChatDebugViewDevtools } from '../ClassNames/ClassNames.ts' +import { createDevtoolsRows } from '../CreateDevtoolsRows/CreateDevtoolsRows.ts' import { createDetailTabs } from '../CreateDetailTabs/CreateDetailTabs.ts' import { getDetailsDom } from '../GetDetailsDom/GetDetailsDom.ts' import { getDevtoolsRows } from '../GetDevtoolsRows/GetDevtoolsRows.ts' @@ -49,7 +50,8 @@ export const getDevtoolsDom = ( maxLineY = events.length, ): readonly VirtualDomNode[] => { const visibleEvents = events.slice(minLineY, maxLineY) - const rowNodes = getDevtoolsRows(visibleEvents, selectedEventIndex, visibleTableColumns, minLineY) + const rows = createDevtoolsRows(visibleEvents, selectedEventIndex, minLineY) + const rowNodes = getDevtoolsRows(rows, visibleTableColumns) const effectiveRange = getEffectiveTimelineRange( timelineStartSeconds, timelineEndSeconds, diff --git a/packages/chat-debug-view/src/parts/GetDevtoolsRows/GetDevtoolsRows.ts b/packages/chat-debug-view/src/parts/GetDevtoolsRows/GetDevtoolsRows.ts index 08100961..cc07baed 100644 --- a/packages/chat-debug-view/src/parts/GetDevtoolsRows/GetDevtoolsRows.ts +++ b/packages/chat-debug-view/src/parts/GetDevtoolsRows/GetDevtoolsRows.ts @@ -1,28 +1,21 @@ import { mergeClassNames, type VirtualDomNode, VirtualDomElements } from '@lvce-editor/virtual-dom-worker' -import type { ChatViewEvent } from '../ChatViewEvent/ChatViewEvent.ts' +import type { DevtoolsRow } from '../DevtoolsRow/DevtoolsRow.ts' import { TableRow, TableRowEven, TableRowOdd, TableRowSelected } from '../ClassNames/ClassNames.ts' import { getRowCellNodes } from '../GetRowCellNodes/GetRowCellNodes.ts' -import { hasErrorStatus } from '../HasErrorStatus/HasErrorStatus.ts' import { defaultVisibleTableColumns } from '../TableColumn/TableColumn.ts' export const getDevtoolsRows = ( - events: readonly ChatViewEvent[], - selectedEventIndex: number | null, + rows: readonly DevtoolsRow[], visibleTableColumns: readonly string[] = defaultVisibleTableColumns, - startIndex = 0, ): readonly VirtualDomNode[] => { - return events.flatMap((event, i) => { - const actualIndex = startIndex + i - const isEvenRow = actualIndex % 2 === 1 - const rowClassName = isEvenRow ? TableRowEven : TableRowOdd - const isSelected = selectedEventIndex === actualIndex - const isErrorStatus = hasErrorStatus(event) - const rowCellNodes = getRowCellNodes(event, isErrorStatus, visibleTableColumns) + return rows.flatMap((row) => { + const rowClassName = row.isEven ? TableRowEven : TableRowOdd + const rowCellNodes = getRowCellNodes(row.event, row.isErrorStatus, visibleTableColumns) return [ { childCount: visibleTableColumns.length, - className: mergeClassNames(TableRow, rowClassName, isSelected ? TableRowSelected : ''), - 'data-index': `${actualIndex}`, + className: mergeClassNames(TableRow, rowClassName, row.isSelected ? TableRowSelected : ''), + 'data-index': `${row.index}`, type: VirtualDomElements.Tr, }, ...rowCellNodes, diff --git a/packages/chat-debug-view/test/CreateDevtoolsRows.test.ts b/packages/chat-debug-view/test/CreateDevtoolsRows.test.ts new file mode 100644 index 00000000..5a2c38d1 --- /dev/null +++ b/packages/chat-debug-view/test/CreateDevtoolsRows.test.ts @@ -0,0 +1,68 @@ +import { expect, test } from '@jest/globals' +import * as CreateDevtoolsRows from '../src/parts/CreateDevtoolsRows/CreateDevtoolsRows.ts' + +test('createDevtoolsRows should derive row state for a virtualized slice', () => { + const events = [ + { + eventId: 3, + sessionId: 'session-1', + timestamp: '2026-03-08T00:00:02.000Z', + type: 'request', + }, + { + eventId: 4, + sessionId: 'session-1', + timestamp: '2026-03-08T00:00:03.000Z', + type: 'response', + }, + ] + + const result = CreateDevtoolsRows.createDevtoolsRows(events, 3, 2) + + expect(result).toEqual([ + { + event: events[0], + index: 2, + isErrorStatus: false, + isEven: false, + isSelected: false, + }, + { + event: events[1], + index: 3, + isErrorStatus: false, + isEven: true, + isSelected: true, + }, + ]) +}) + +test('createDevtoolsRows should mark error rows from event status', () => { + const events = [ + { + arguments: { + uri: '/test/playground', + }, + eventId: 1, + name: 'list_files', + result: { + error: 'Invalid argument: uri must be an absolute URI.', + }, + sessionId: 'session-1', + timestamp: '2026-04-02T07:26:35.172Z', + type: 'tool-execution', + }, + ] + + const result = CreateDevtoolsRows.createDevtoolsRows(events, null) + + expect(result).toEqual([ + { + event: events[0], + index: 0, + isErrorStatus: true, + isEven: false, + isSelected: false, + }, + ]) +}) diff --git a/packages/chat-debug-view/test/GetDevtoolsRows.test.ts b/packages/chat-debug-view/test/GetDevtoolsRows.test.ts index 78f5c106..6f2f89bc 100644 --- a/packages/chat-debug-view/test/GetDevtoolsRows.test.ts +++ b/packages/chat-debug-view/test/GetDevtoolsRows.test.ts @@ -1,8 +1,20 @@ import { expect, test } from '@jest/globals' import { VirtualDomElements, text } from '@lvce-editor/virtual-dom-worker' +import type { DevtoolsRow } from '../src/parts/DevtoolsRow/DevtoolsRow.ts' import * as GetDevtoolsRows from '../src/parts/GetDevtoolsRows/GetDevtoolsRows.ts' import * as TableColumn from '../src/parts/TableColumn/TableColumn.ts' +const createRow = (event: Record, index = 0, overrides: Partial = {}): DevtoolsRow => { + return { + event: event as DevtoolsRow['event'], + index, + isErrorStatus: false, + isEven: index % 2 === 1, + isSelected: false, + ...overrides, + } +} + test('getDevtoolsRows should render tool execution labels with the tool name', () => { const events = [ { @@ -14,7 +26,7 @@ test('getDevtoolsRows should render tool execution labels with the tool name', ( }, ] - const result = GetDevtoolsRows.getDevtoolsRows(events, null) + const result = GetDevtoolsRows.getDevtoolsRows([createRow(events[0])]) expect(result).toEqual([ { @@ -64,7 +76,7 @@ test('getDevtoolsRows should render tool execution labels with tool name from ar }, ] - const result = GetDevtoolsRows.getDevtoolsRows(events, null) + const result = GetDevtoolsRows.getDevtoolsRows([createRow(events[0])]) expect(result).toEqual([ { @@ -116,7 +128,7 @@ test('getDevtoolsRows should render tool execution labels with tool name from to }, ] - const result = GetDevtoolsRows.getDevtoolsRows(events, null) + const result = GetDevtoolsRows.getDevtoolsRows([createRow(events[0], 0, { isErrorStatus: true })]) expect(result).toEqual([ { @@ -169,7 +181,7 @@ test('getDevtoolsRows should render 400 status when tool error is nested in resu }, ] - const result = GetDevtoolsRows.getDevtoolsRows(events, null) + const result = GetDevtoolsRows.getDevtoolsRows([createRow(events[0], 0, { isErrorStatus: true })]) expect(result).toEqual([ { @@ -221,7 +233,7 @@ test('getDevtoolsRows should add odd and even row classes to table rows', () => }, ] - const result = GetDevtoolsRows.getDevtoolsRows(events, null) + const result = GetDevtoolsRows.getDevtoolsRows([createRow(events[0]), createRow(events[1], 1)]) expect(result).toEqual([ { @@ -312,7 +324,7 @@ test('getDevtoolsRows should render merged ai request duration from timestamps', }, ] - const result = GetDevtoolsRows.getDevtoolsRows(events, null) + const result = GetDevtoolsRows.getDevtoolsRows([createRow(events[0])]) expect(result).toEqual([ { @@ -360,7 +372,7 @@ test('getDevtoolsRows should omit hidden columns', () => { }, ] - const result = GetDevtoolsRows.getDevtoolsRows(events, null, [TableColumn.Type, TableColumn.Status]) + const result = GetDevtoolsRows.getDevtoolsRows([createRow(events[0])], [TableColumn.Type, TableColumn.Status]) expect(result).toEqual([ { @@ -400,7 +412,10 @@ test('getDevtoolsRows should preserve row parity and selection for a virtualized }, ] - const result = GetDevtoolsRows.getDevtoolsRows(events, 3, TableColumn.defaultVisibleTableColumns, 2) + const result = GetDevtoolsRows.getDevtoolsRows( + [createRow(events[0], 2), createRow(events[1], 3, { isEven: true, isSelected: true })], + TableColumn.defaultVisibleTableColumns, + ) expect(result).toEqual([ { From 9a9cb1ab47e58f8fdcb8bd88ee96bb0ddf4ae8f7 Mon Sep 17 00:00:00 2001 From: Le Vivilet Date: Sun, 10 May 2026 20:01:35 +0000 Subject: [PATCH 2/3] memory --- packages/build/src/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/build/src/config.ts b/packages/build/src/config.ts index 73877b4a..0192978c 100644 --- a/packages/build/src/config.ts +++ b/packages/build/src/config.ts @@ -1,7 +1,7 @@ import { join } from 'node:path' import { root } from './root.ts' -export const threshold = 600_000 +export const threshold = 620_000 export const instantiations = 200_000 From b495eb57da264b9b4663fe917240bf67535611a5 Mon Sep 17 00:00:00 2001 From: Le Vivilet Date: Sun, 10 May 2026 20:03:19 +0000 Subject: [PATCH 3/3] fix --- .../chat-debug-view/src/parts/GetDevtoolsDom/GetDevtoolsDom.ts | 2 +- packages/chat-debug-view/test/GetDevtoolsRows.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/chat-debug-view/src/parts/GetDevtoolsDom/GetDevtoolsDom.ts b/packages/chat-debug-view/src/parts/GetDevtoolsDom/GetDevtoolsDom.ts index 255a9881..e97b22d5 100644 --- a/packages/chat-debug-view/src/parts/GetDevtoolsDom/GetDevtoolsDom.ts +++ b/packages/chat-debug-view/src/parts/GetDevtoolsDom/GetDevtoolsDom.ts @@ -4,8 +4,8 @@ import type { DetailTab as DetailTabType } from '../DetailTab/DetailTab.ts' import type { TimelineInfo } from '../GetTimelineInfo/GetTimelineInfo.ts' import * as ChatDebugStrings from '../ChatDebugStrings/ChatDebugStrings.ts' import { ChatDebugView, ChatDebugViewDevtools } from '../ClassNames/ClassNames.ts' -import { createDevtoolsRows } from '../CreateDevtoolsRows/CreateDevtoolsRows.ts' import { createDetailTabs } from '../CreateDetailTabs/CreateDetailTabs.ts' +import { createDevtoolsRows } from '../CreateDevtoolsRows/CreateDevtoolsRows.ts' import { getDetailsDom } from '../GetDetailsDom/GetDetailsDom.ts' import { getDevtoolsRows } from '../GetDevtoolsRows/GetDevtoolsRows.ts' import { getEffectiveTimelineRange } from '../GetEffectiveTimelineRange/GetEffectiveTimelineRange.ts' diff --git a/packages/chat-debug-view/test/GetDevtoolsRows.test.ts b/packages/chat-debug-view/test/GetDevtoolsRows.test.ts index 6f2f89bc..909b8cce 100644 --- a/packages/chat-debug-view/test/GetDevtoolsRows.test.ts +++ b/packages/chat-debug-view/test/GetDevtoolsRows.test.ts @@ -4,7 +4,7 @@ import type { DevtoolsRow } from '../src/parts/DevtoolsRow/DevtoolsRow.ts' import * as GetDevtoolsRows from '../src/parts/GetDevtoolsRows/GetDevtoolsRows.ts' import * as TableColumn from '../src/parts/TableColumn/TableColumn.ts' -const createRow = (event: Record, index = 0, overrides: Partial = {}): DevtoolsRow => { +const createRow = (event: Readonly>, index = 0, overrides: Readonly> = {}): DevtoolsRow => { return { event: event as DevtoolsRow['event'], index,