Skip to content

Commit 05f47ec

Browse files
committed
fix(orchestrator): Keep terminal provider errors visible
1 parent bf43aa3 commit 05f47ec

3 files changed

Lines changed: 73 additions & 1 deletion

File tree

‎apps/web/src/components/ChatView.tsx‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7388,6 +7388,7 @@ function ChatViewContent(props: ChatViewProps) {
73887388
<MessagesTimeline
73897389
key={activeThread.id}
73907390
isWorking={isWorking}
7391+
activeTurnInProgress={isWorking || !latestRunSettled}
73917392
activeTurnStartedAt={activeWorkStartedAt}
73927393
isPreparingWorktree={isPreparingWorktree || activeRunPreparing}
73937394
listRef={legendListRef}

‎apps/web/src/components/chat/MessagesTimeline.logic.test.ts‎

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -916,6 +916,64 @@ describe("deriveMessagesTimelineRows", () => {
916916
]);
917917
});
918918

919+
it("keeps a terminal provider error visible when no assistant message was produced", () => {
920+
const runId = "turn-provider-error" as never;
921+
const rows = deriveMessagesTimelineRows({
922+
timelineEntries: [
923+
{
924+
id: "user-entry",
925+
kind: "message",
926+
createdAt: "2026-01-01T00:00:00Z",
927+
message: {
928+
id: "user-provider-error" as never,
929+
role: "user",
930+
text: "Start the turn",
931+
runId,
932+
createdAt: "2026-01-01T00:00:00Z",
933+
updatedAt: "2026-01-01T00:00:00Z",
934+
streaming: false,
935+
},
936+
},
937+
{
938+
id: "provider-error-entry",
939+
kind: "work",
940+
createdAt: "2026-01-01T00:00:08Z",
941+
entry: {
942+
id: "provider-error",
943+
createdAt: "2026-01-01T00:00:08Z",
944+
runId,
945+
label: "Provider error",
946+
detail: "The model is currently at capacity.",
947+
tone: "info",
948+
itemType: "error",
949+
toolLifecycleStatus: "failed",
950+
},
951+
},
952+
],
953+
latestRun: {
954+
runId,
955+
status: "failed",
956+
startedAt: "2026-01-01T00:00:00Z",
957+
completedAt: "2026-01-01T00:00:08Z",
958+
},
959+
isWorking: false,
960+
activeTurnStartedAt: null,
961+
turnDiffSummaryByAssistantMessageId: new Map(),
962+
revertTurnCountByUserMessageId: new Map(),
963+
});
964+
965+
expect(rows.map((row) => row.id)).toEqual(["user-entry", "provider-error-entry"]);
966+
expect(rows.some((row) => row.kind === "turn-fold")).toBe(false);
967+
expect(rows.find((row) => row.kind === "work")).toMatchObject({
968+
groupedEntries: [
969+
expect.objectContaining({
970+
id: "provider-error",
971+
detail: "The model is currently at capacity.",
972+
}),
973+
],
974+
});
975+
});
976+
919977
it("keeps persistent cards after the Worked-for row when they arrive before commentary", () => {
920978
const timelineEntries = [
921979
{

‎apps/web/src/components/chat/MessagesTimeline.logic.ts‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export function workEntryIsVisibleInGroup(
5757
workEntryShouldRenderInWorkLog(entry)
5858
);
5959
}
60+
export const MAX_VISIBLE_WORK_LOG_ENTRIES = 1;
6061
export const TIMELINE_MINIMAP_ITEM_SPACING = 8;
6162
export const TIMELINE_MINIMAP_MIN_ITEMS = 2;
6263
export const TIMELINE_MINIMAP_MAX_HEIGHT_CSS = "calc(100vh - 18rem)";
@@ -687,6 +688,14 @@ function timelineEntryFoldRunId(entry: TimelineEntry): RunId | null {
687688
return null;
688689
}
689690

691+
function timelineEntryIsTerminalError(entry: TimelineEntry): boolean {
692+
return (
693+
entry.kind === "work" &&
694+
entry.entry.itemType === "error" &&
695+
entry.entry.toolLifecycleStatus === "failed"
696+
);
697+
}
698+
690699
/**
691700
* Settled turns fold their commentary and tool activity behind a
692701
* "Worked for ..." row anchored at the turn's first foldable entry; the
@@ -769,7 +778,11 @@ function deriveTurnFolds(input: {
769778
}
770779
const hiddenEntryIds = new Set<string>();
771780
for (const entry of group.entries) {
772-
if (entry.id !== group.terminalEntry?.id && !timelineEntryIsPersistentResourceCard(entry)) {
781+
if (
782+
entry.id !== group.terminalEntry?.id &&
783+
!timelineEntryIsPersistentResourceCard(entry) &&
784+
!timelineEntryIsTerminalError(entry)
785+
) {
773786
hiddenEntryIds.add(entry.id);
774787
}
775788
}

0 commit comments

Comments
 (0)