fix(ui): show delegated work on selected threads (#129328)

Fixes #129318

Co-authored-by: roboclaw-bot <309084314+roboclaw-bot@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
This commit is contained in:
RoboClaw
2026-08-25 18:07:10 -07:00
committed by GitHub
parent cc1c61034f
commit d6510fa961
5 changed files with 28 additions and 17 deletions
@@ -2674,10 +2674,10 @@ describe("gateway server chat", () => {
8_000,
);
blockedReply.resolve();
await waitForAgentRunOk(runId);
const settledEvent = await settledSessionChange.catch(() => {
throw new Error("Gateway did not publish settled run ownership after chat.send cleanup");
});
await waitForAgentRunOk(runId);
expectRecordFields(settledEvent.payload, {
activeRunIds: [],
hasActiveRun: false,
@@ -231,11 +231,12 @@ export class AppSidebarSessionNavigationElement extends AppSidebarBase {
pending.push(...session.children);
if (
session.childSessionKeys.length > 0 &&
this.isSessionChildrenExpanded(session) &&
(session.visuallyActive || this.isSessionChildrenExpanded(session)) &&
!this.sessionData.loadedChildSessionKeys.has(session.key) &&
!this.sessionData.childSessionErrorsByParent.has(session.key) &&
!this.sessionData.loadingChildSessionKeys.has(session.key)
) {
// Selected collapsed rows need child liveness so delegated work does not look finished.
void this.sessionData.loadChildSessions(session.key);
}
}
@@ -50,18 +50,22 @@ export function renderSessionRunSpinner(showTitle = true) {
></span>`;
}
export function sessionHasRunningWork(session: SidebarRecentSession): boolean {
return session.hasActiveRun || session.runningChildCount > 0;
}
export function renderSessionState(session: SidebarRecentSession, showTitle = true) {
if (session.hasActiveRun) {
if (session.status === "queued") {
const label = t("sessionsView.statusQueued");
return html`<span
class="sidebar-child-session__status sidebar-child-session__status--queued"
role="img"
aria-label=${label}
title=${showTitle ? label : nothing}
>${icons.hourglass}</span
>`;
}
if (session.hasActiveRun && session.status === "queued") {
const label = t("sessionsView.statusQueued");
return html`<span
class="sidebar-child-session__status sidebar-child-session__status--queued"
role="img"
aria-label=${label}
title=${showTitle ? label : nothing}
>${icons.hourglass}</span
>`;
}
if (sessionHasRunningWork(session)) {
return renderSessionRunSpinner(showTitle);
}
if (!session.isChild) {
@@ -5,6 +5,7 @@ import { icons } from "./icons.ts";
import {
renderSessionAttentionIcon,
renderSessionState,
sessionHasRunningWork,
} from "./session-attention-presentation.ts";
import {
renderSessionGlyph,
@@ -97,12 +98,14 @@ export function describeSessionTrailingState(
session: SidebarRecentSession,
pullRequestState: SessionPullRequestIndicatorState,
) {
const runningLabel =
session.hasActiveRun && session.status === "queued"
? t("sessionsView.statusQueued")
: t("sessionsView.activeRun");
return [
session.forkSource ? t("sessionsView.forkedSession") : "",
pullRequestState === "none" ? "" : pullRequestStateLabel(pullRequestState),
session.hasActiveRun
? t(session.status === "queued" ? "sessionsView.statusQueued" : "sessionsView.activeRun")
: "",
sessionHasRunningWork(session) ? runningLabel : "",
session.unread ? t("sessionsView.unread") : "",
]
.filter(Boolean)
@@ -124,7 +127,7 @@ export function renderSessionLeadingState(
trailingIndicator: TemplateResult | typeof nothing;
renderedOwnerId?: string;
} {
const running = session.hasActiveRun;
const running = sessionHasRunningWork(session);
const trailingIndicator = session.isChild
? nothing
: renderSessionTrailingState(session, pullRequestState);
@@ -166,6 +166,9 @@ suite.define(() => {
const parent = page.locator(`[data-session-key="${parentKey}"]`);
await parent.waitFor({ state: "visible", timeout: 10_000 });
await expect.poll(() => page.locator(".sidebar-recent-session--child").count()).toBe(0);
await expect
.poll(() => parent.locator(".session-run-spinner").getAttribute("aria-label"))
.toBe("Active run");
await captureUiProof(page, "child-sessions-collapsed.png");
await parent.getByRole("button", { name: "Show 4 child sessions for Plan release" }).click();