story-kit: merge 290_story_show_agent_output_stream_in_expanded_work_item_detail_panel

This commit is contained in:
Dave
2026-03-18 15:28:08 +00:00
parent 68bf179407
commit 83ccfece81
3 changed files with 129 additions and 205 deletions

View File

@@ -213,7 +213,7 @@ describe("RosterBadge availability state", () => {
});
});
describe("Thinking traces hidden from agent stream UI", () => {
describe("Agent output not shown in sidebar (story 290)", () => {
beforeAll(() => {
Element.prototype.scrollIntoView = vi.fn();
});
@@ -224,7 +224,51 @@ describe("Thinking traces hidden from agent stream UI", () => {
mockedSubscribeAgentStream.mockReturnValue(() => {});
});
// AC1: thinking block is never rendered even when thinking events arrive
// AC1: output events do not appear in the agents sidebar
it("does not render agent output when output event arrives", async () => {
let emitEvent: ((e: AgentEvent) => void) | null = null;
mockedSubscribeAgentStream.mockImplementation(
(_storyId, _agentName, onEvent) => {
emitEvent = onEvent;
return () => {};
},
);
const agentList: AgentInfo[] = [
{
story_id: "290_output",
agent_name: "coder-1",
status: "running",
session_id: null,
worktree_path: "/tmp/wt",
base_branch: "master",
log_session_id: null,
},
];
mockedAgents.listAgents.mockResolvedValue(agentList);
const { container } = render(<AgentPanel />);
await screen.findByTestId("roster-badge-coder-1");
await act(async () => {
emitEvent?.({
type: "output",
story_id: "290_output",
agent_name: "coder-1",
text: "doing some work...",
});
});
// No output elements in the sidebar
expect(
container.querySelector('[data-testid^="agent-output-"]'),
).not.toBeInTheDocument();
expect(
container.querySelector('[data-testid^="agent-stream-"]'),
).not.toBeInTheDocument();
});
// AC1: thinking events do not appear in the agents sidebar
it("does not render thinking block when thinking event arrives", async () => {
let emitEvent: ((e: AgentEvent) => void) | null = null;
mockedSubscribeAgentStream.mockImplementation(
@@ -236,7 +280,7 @@ describe("Thinking traces hidden from agent stream UI", () => {
const agentList: AgentInfo[] = [
{
story_id: "218_thinking",
story_id: "290_thinking",
agent_name: "coder-1",
status: "running",
session_id: null,
@@ -253,109 +297,16 @@ describe("Thinking traces hidden from agent stream UI", () => {
await act(async () => {
emitEvent?.({
type: "thinking",
story_id: "218_thinking",
story_id: "290_thinking",
agent_name: "coder-1",
text: "Let me consider the problem carefully...",
});
});
// AC1: thinking block must not be present
// No thinking block or output in sidebar
expect(screen.queryByTestId("thinking-block")).not.toBeInTheDocument();
});
// AC2: after thinking events, only regular output is rendered
it("renders regular output but not thinking block when both arrive", async () => {
let emitEvent: ((e: AgentEvent) => void) | null = null;
mockedSubscribeAgentStream.mockImplementation(
(_storyId, _agentName, onEvent) => {
emitEvent = onEvent;
return () => {};
},
);
const agentList: AgentInfo[] = [
{
story_id: "218_output",
agent_name: "coder-1",
status: "running",
session_id: null,
worktree_path: "/tmp/wt",
base_branch: "master",
log_session_id: null,
},
];
mockedAgents.listAgents.mockResolvedValue(agentList);
render(<AgentPanel />);
await screen.findByTestId("roster-badge-coder-1");
// Thinking event — must be ignored visually
await act(async () => {
emitEvent?.({
type: "thinking",
story_id: "218_output",
agent_name: "coder-1",
text: "thinking deeply",
});
});
// AC3: output event still renders correctly (no regression)
await act(async () => {
emitEvent?.({
type: "output",
story_id: "218_output",
agent_name: "coder-1",
text: "Here is the result.",
});
});
// AC1: no thinking block
expect(screen.queryByTestId("thinking-block")).not.toBeInTheDocument();
// AC2+AC3: output area renders the text but NOT thinking text
const outputArea = screen.getByTestId("agent-output-coder-1");
expect(outputArea).toBeInTheDocument();
expect(outputArea.textContent).toContain("Here is the result.");
expect(outputArea.textContent).not.toContain("thinking deeply");
});
// AC3: output-only event stream (no thinking) still works
it("renders output event text without a thinking block", async () => {
let emitEvent: ((e: AgentEvent) => void) | null = null;
mockedSubscribeAgentStream.mockImplementation(
(_storyId, _agentName, onEvent) => {
emitEvent = onEvent;
return () => {};
},
);
const agentList: AgentInfo[] = [
{
story_id: "218_noThink",
agent_name: "coder-1",
status: "running",
session_id: null,
worktree_path: "/tmp/wt",
base_branch: "master",
log_session_id: null,
},
];
mockedAgents.listAgents.mockResolvedValue(agentList);
render(<AgentPanel />);
await screen.findByTestId("roster-badge-coder-1");
await act(async () => {
emitEvent?.({
type: "output",
story_id: "218_noThink",
agent_name: "coder-1",
text: "plain output line",
});
});
expect(screen.queryByTestId("thinking-block")).not.toBeInTheDocument();
const outputArea = screen.getByTestId("agent-output-coder-1");
expect(outputArea.textContent).toContain("plain output line");
expect(
screen.queryByText("Let me consider the problem carefully..."),
).not.toBeInTheDocument();
});
});