From b7bd6268e8bf11f6dab0c1cf91c6284827ec8a94 Mon Sep 17 00:00:00 2001 From: "@mrubens" <2600+mrubens@users.noreply.github.com> Date: Fri, 28 Aug 2026 16:01:20 +0000 Subject: [PATCH 1/2] feat(web): show task summaries in session execution details --- .../SessionWorkspace.client.test.tsx | 239 +++++++++++++++++- .../sessions/[sessionId]/SessionWorkspace.tsx | 75 ++++++ 2 files changed, 306 insertions(+), 8 deletions(-) diff --git a/apps/web/src/app/(sandbox)/sessions/[sessionId]/SessionWorkspace.client.test.tsx b/apps/web/src/app/(sandbox)/sessions/[sessionId]/SessionWorkspace.client.test.tsx index df1b51ca5..5db8c6851 100644 --- a/apps/web/src/app/(sandbox)/sessions/[sessionId]/SessionWorkspace.client.test.tsx +++ b/apps/web/src/app/(sandbox)/sessions/[sessionId]/SessionWorkspace.client.test.tsx @@ -12,13 +12,19 @@ import { SandboxLayoutContext } from '../../use-sandbox-layout'; import { SessionWorkspace, type SessionInfo } from './SessionWorkspace'; import { useOpenSessionTaskPanel } from './session-task-panel-context'; -const { useMediaQueryMock, sessionQueryState, fastTaskQueryState } = vi.hoisted( - () => ({ - useMediaQueryMock: vi.fn(), - sessionQueryState: { data: null as unknown }, - fastTaskQueryState: { data: null as unknown }, - }), -); +const { + useMediaQueryMock, + sessionQueryState, + fastTaskQueryState, + searchParamsRef, + useTaskSummaryMock, +} = vi.hoisted(() => ({ + useMediaQueryMock: vi.fn(), + sessionQueryState: { data: null as unknown }, + fastTaskQueryState: { data: null as unknown }, + searchParamsRef: { current: new URLSearchParams() }, + useTaskSummaryMock: vi.fn(), +})); vi.mock('usehooks-ts', () => ({ useMediaQuery: useMediaQueryMock, @@ -26,7 +32,19 @@ vi.mock('usehooks-ts', () => ({ vi.mock('next/navigation', () => ({ useRouter: () => ({ replace: vi.fn() }), - useSearchParams: () => new URLSearchParams(), + useSearchParams: () => searchParamsRef.current, +})); + +vi.mock('streamdown', () => ({ + Streamdown: ({ children }: { children: ReactNode }) =>
+ New activity is not included yet.{' '} + +
+ ) : null} +{errorMessage}
+ ++ {fallbackSummary} +
+ ) : ( ++ {enabled || task.state === 'active' + ? 'A summary will appear as this execution progresses.' + : 'No summary is available for this execution yet.'} +
+ )} +
Execution details require task access.
From 0750fe30a47db737cef6d91025d6a58f675c0b72 Mon Sep 17 00:00:00 2001
From: "@mrubens" <2600+mrubens@users.noreply.github.com>
Date: Fri, 28 Aug 2026 16:23:17 +0000
Subject: [PATCH 2/2] fix(web): show summaries for Fast-only session tasks
---
.../SessionWorkspace.client.test.tsx | 61 ++++++++
.../sessions/[sessionId]/SessionWorkspace.tsx | 140 +++++++++++++++++-
2 files changed, 196 insertions(+), 5 deletions(-)
diff --git a/apps/web/src/app/(sandbox)/sessions/[sessionId]/SessionWorkspace.client.test.tsx b/apps/web/src/app/(sandbox)/sessions/[sessionId]/SessionWorkspace.client.test.tsx
index 5db8c6851..ce8dfba10 100644
--- a/apps/web/src/app/(sandbox)/sessions/[sessionId]/SessionWorkspace.client.test.tsx
+++ b/apps/web/src/app/(sandbox)/sessions/[sessionId]/SessionWorkspace.client.test.tsx
@@ -18,12 +18,14 @@ const {
fastTaskQueryState,
searchParamsRef,
useTaskSummaryMock,
+ useTaskMock,
} = vi.hoisted(() => ({
useMediaQueryMock: vi.fn(),
sessionQueryState: { data: null as unknown },
fastTaskQueryState: { data: null as unknown },
searchParamsRef: { current: new URLSearchParams() },
useTaskSummaryMock: vi.fn(),
+ useTaskMock: vi.fn(),
}));
vi.mock('usehooks-ts', () => ({
@@ -47,6 +49,10 @@ vi.mock('../../task/[taskId]/hooks/use-task-summary', () => ({
useTaskSummary: useTaskSummaryMock,
}));
+vi.mock('@/hooks/tasks/useTask', () => ({
+ useTask: useTaskMock,
+}));
+
vi.mock('@/hooks/task-models/useLaunchTaskModels', () => ({
useLaunchTaskModels: () => ({
data: { models: [{ id: 'model-1', displayName: 'Model One' }] },
@@ -227,6 +233,11 @@ describe('SessionWorkspace', () => {
isSummaryStale: false,
regenerateSummary: vi.fn(),
});
+ useTaskMock.mockReturnValue({
+ data: null,
+ isPending: false,
+ isError: false,
+ });
});
it('matches the task sidebar replacement behavior and controls on mobile', () => {
@@ -399,6 +410,56 @@ describe('SessionWorkspace', () => {
expect(useTaskSummaryMock).toHaveBeenCalledWith('task-1');
});
+ it('shows execution details for a selected Fast-only session task', () => {
+ useTaskSummaryMock.mockReturnValue({
+ enabled: true,
+ summary: 'The Fast task completed its delegated work.',
+ isLoadingSummary: false,
+ errorMessage: null,
+ isSummaryStale: false,
+ regenerateSummary: vi.fn(),
+ });
+ useTaskMock.mockReturnValue({
+ data: {
+ id: 'task-1',
+ title: 'Fast delegated task',
+ workflow: 'standard',
+ state: 'completed',
+ repositoryName: 'RooCodeInc/Roomote',
+ taskRun: {
+ id: 1,
+ status: 'completed',
+ taskPhase: null,
+ error: null,
+ result: null,
+ pullRequests: [],
+ },
+ artifacts: [],
+ inferenceUsage: { eventCount: 1, costMicroUsd: 100 },
+ },
+ isPending: false,
+ isError: false,
+ });
+
+ renderWorkspace({
+ isMobile: false,
+ selectedTaskId: 'task-1',
+ sessionOverride: {
+ taskSource: 'fast',
+ tasks: [],
+ taskCards: [{ taskId: 'task-1', title: 'Fast delegated task' }],
+ },
+ });
+
+ expect(
+ screen.getByText('The Fast task completed its delegated work.'),
+ ).toBeInTheDocument();
+ expect(useTaskSummaryMock).toHaveBeenCalledWith('task-1');
+ expect(useTaskMock).toHaveBeenCalledWith('task-1', true, {
+ refetchInterval: 2_000,
+ });
+ });
+
it('shows loading and retryable error states for task summaries', () => {
useTaskSummaryMock.mockReturnValue({
enabled: true,
diff --git a/apps/web/src/app/(sandbox)/sessions/[sessionId]/SessionWorkspace.tsx b/apps/web/src/app/(sandbox)/sessions/[sessionId]/SessionWorkspace.tsx
index 6ad66d519..6c4ebc4ee 100644
--- a/apps/web/src/app/(sandbox)/sessions/[sessionId]/SessionWorkspace.tsx
+++ b/apps/web/src/app/(sandbox)/sessions/[sessionId]/SessionWorkspace.tsx
@@ -24,6 +24,7 @@ import {
getSessionSurfaceLabel,
} from '@/components/sessions/session-surfaces';
import { useLaunchTaskModels } from '@/hooks/task-models/useLaunchTaskModels';
+import { useTask } from '@/hooks/tasks/useTask';
import { useTRPC } from '@/trpc/client';
import { FramedSurface, WorkspaceSurface } from '@/components/layout';
import { SideNavItem } from '@/components/layout/side-nav/SideNavItem';
@@ -36,6 +37,7 @@ import {
Button,
Calendar,
DollarSign,
+ ErrorState,
Globe,
Info,
Slack,
@@ -164,7 +166,7 @@ function SessionTaskPanel({
}: {
sessionId: string;
task: SessionTaskSummary;
- tasks: SessionTaskSummary[];
+ tasks: Array