Skip to content

Commit 7ffce8a

Browse files
authored
fix(canvas): render agent status as thread content
Generated-By: PostHog Code Task-Id: 87a79e23-20c4-440b-818b-28154924ffbc
1 parent f723ed9 commit 7ffce8a

4 files changed

Lines changed: 37 additions & 8 deletions

File tree

packages/core/src/canvas/threadTimeline.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ describe("deriveThreadAgentStatus", () => {
7272
input: { hasActivity: true, hasPullRequest: true },
7373
expected: { phase: "complete", label: "Shipped" },
7474
},
75+
{
76+
name: "reports settled work without a pull request as done",
77+
input: { hasActivity: true },
78+
expected: { phase: "complete", label: "Done" },
79+
},
7580
])("$name", ({ input, expected }) => {
7681
expect(deriveThreadAgentStatus(input)).toEqual(expected);
7782
});

packages/core/src/canvas/threadTimeline.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ export function deriveThreadAgentStatus({
9999
}
100100
return {
101101
phase: "complete",
102-
label: hasPullRequest ? "Shipped" : "Ready to ship",
102+
label: hasPullRequest ? "Shipped" : "Done",
103103
};
104104
}
105105

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { render, screen } from "@testing-library/react";
2+
import { describe, expect, it } from "vitest";
3+
import { AgentTurnRow } from "./ThreadPanel";
4+
5+
describe("AgentTurnRow", () => {
6+
it.each([
7+
{ phase: "active" as const, label: "Working…" },
8+
{ phase: "complete" as const, label: "Done" },
9+
])("renders $label in the message area", (statusValue) => {
10+
render(<AgentTurnRow status={statusValue} streaming={false} />);
11+
12+
const author = screen.getByText("Agent");
13+
const status = screen.getByText(statusValue.label);
14+
15+
expect(author.parentElement).not.toContainElement(status);
16+
expect(author.closest("article")).toContainElement(status);
17+
expect(status.closest('[data-slot="thread-item-body"]')).not.toBeNull();
18+
});
19+
});

packages/ui/src/features/canvas/components/ThreadPanel.tsx

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ function AgentStatusChip({ status }: { status: ThreadAgentStatus }) {
211211
}
212212
}
213213

214-
function AgentTurnRow({
214+
export function AgentTurnRow({
215215
message,
216216
status,
217217
streaming,
@@ -232,20 +232,25 @@ function AgentTurnRow({
232232
<ThreadItemContent>
233233
<ThreadItemHeader>
234234
<ThreadItemAuthor>Agent</ThreadItemAuthor>
235-
{status && <AgentStatusChip status={status} />}
236235
{message?.timestamp !== undefined && (
237236
<ThreadTimestamp
238237
dateTime={new Date(message.timestamp).toISOString()}
239238
/>
240239
)}
241240
</ThreadItemHeader>
242-
{message?.text && (
241+
{(message?.text || status) && (
243242
<ThreadItemBody>
244243
<div className="rounded-md border border-border bg-muted px-2 py-1.5">
245-
{streaming ? (
246-
<ChatStreamingMarkdown content={message.text} />
247-
) : (
248-
<ChatMarkdown content={message.text} />
244+
{message?.text &&
245+
(streaming ? (
246+
<ChatStreamingMarkdown content={message.text} />
247+
) : (
248+
<ChatMarkdown content={message.text} />
249+
))}
250+
{status && (
251+
<div className={message?.text ? "mt-2" : undefined}>
252+
<AgentStatusChip status={status} />
253+
</div>
249254
)}
250255
</div>
251256
</ThreadItemBody>

0 commit comments

Comments
 (0)