Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
53 changes: 53 additions & 0 deletions apps/webview/e2e/browser-smoke.e2e.mts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@ const viteCli = fileURLToPath(new URL('../../bin/vite.js', import.meta.resolve('
const newSessionDefaultsKey = 'linkcode.workbench.new-session-defaults:v7';
const mockThreadTitle = 'Wire the workbench to the daemon';
const mockChatThreadTitle = 'Prototype without git';
const showcaseThreadTitle = 'Mocked streaming showcase';
const longThreadTitle = 'Long thread · navigation testbed';
const longThreadTurns = 48;
const maxMountedRows = 10;
const RE_ACTIVITY_RUN_DETAILS =
/^Activity details: .*failed.*ran .*command.*made .*file change.*explored.*$/iu;
const RE_LONG_THREAD_TURN = /Turn (\d+) —/g;

interface ViteServer {
Expand Down Expand Up @@ -126,6 +129,55 @@ async function verifyNewChatIsolation(page: Page, appErrors: string[]): Promise<
assertNoApplicationErrors(appErrors);
}

async function verifyActivityRunHierarchy(page: Page): Promise<void> {
await page.locator('[data-thread-title]', { hasText: showcaseThreadTitle }).click();
await page.locator('[data-conversation-title]', { hasText: showcaseThreadTitle }).waitFor();

const runHeader = page.getByRole('button', {
name: RE_ACTIVITY_RUN_DETAILS,
});
await runHeader.waitFor({ timeout: 15000 });
await runHeader.click();

const metrics = await runHeader.evaluate((header) => {
const group = header.closest('[data-slot="collapsible"]');
const body = group?.querySelector(
':scope > [data-slot="collapsible-panel"] [data-slot="scroll-area-content"] > div',
);
if (!(body instanceof HTMLElement)) throw new Error('Missing expanded activity body');

const children = [...body.children].map((row) => {
const child = row.firstElementChild;
if (!(child instanceof HTMLElement)) throw new Error('Missing activity child header');
return {
paddingBlockStart: Number.parseFloat(getComputedStyle(child).paddingBlockStart),
slot: child.dataset.slot,
tagName: child.tagName,
};
});
return {
children,
paddingBlockStart: Number.parseFloat(getComputedStyle(header).paddingBlockStart),
};
});

assert.ok(metrics.children.length >= 5, 'Mixed activity run did not render every child');
assert.ok(
metrics.children.some((child) => child.slot === 'tooltip-trigger'),
`No tooltip-backed activity row rendered: ${JSON.stringify(metrics.children)}`,
);
assert.ok(
metrics.children.some((child) => child.tagName === 'DIV'),
`No bodyless activity row rendered: ${JSON.stringify(metrics.children)}`,
);
assert.ok(
metrics.children.every(
(child) => child.paddingBlockStart > 0 && child.paddingBlockStart < metrics.paddingBlockStart,
),
`Activity children were not denser than the group: ${JSON.stringify(metrics)}`,
);
}

async function verifyLongThreadVirtualization(page: Page): Promise<void> {
await page.evaluate(
({ flags, source }) => {
Expand Down Expand Up @@ -372,6 +424,7 @@ async function verifyMockEntry(browser: Browser): Promise<void> {
const recoveryPrompt = `${firstPrompt}-after-reload`;
await sendPrompt(page, recoveryPrompt, appErrors);
await verifyNewChatIsolation(page, appErrors);
await verifyActivityRunHierarchy(page);
await verifyLongThreadVirtualization(page);
assertNoApplicationErrors(appErrors);
await page.close();
Expand Down
7 changes: 7 additions & 0 deletions packages/client/workbench/src/mock/data/showcase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,13 @@ export function createShowcaseToolBursts(terminalId = SHOWCASE_TERMINAL_ID): Sho
content: [],
rawInput: { path: 'packages/presentation/ui/src/chat/activity-groups.ts' },
},
{
toolCallId: 'mock-activity-read-bodyless',
title: 'Inspect activity boundaries',
kind: 'read',
status: 'completed',
content: [],
},
{
toolCallId: 'mock-activity-execute-failed',
title: 'Run compact activity check',
Expand Down
2 changes: 1 addition & 1 deletion packages/presentation/ui/src/chat/activity-run.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export function ActivityRun({
) : null}
<ChatDisclosureChevron />
</CollapsibleTrigger>
<ChatDisclosureContent bodyClassName="space-y-0.5">
<ChatDisclosureContent bodyClassName="space-y-0.5 [&>[data-slot=collapsible]>*:first-child]:py-0.5">
{run.items.map((item) => {
if (item.kind === 'reasoning') {
return (
Expand Down