feat(FN-3275): unify AgentDetailView header with planning and harden resear

This merge adds idempotent cancel/retry and SSE streaming to the research lifecycle (FN-2999), tightens mobile spacing in the AgentDetailView header cluster (FN-3275), and wires the planning mode into the agent detail header actions (FN-3238). Research orchestrator, store, routes, and the SSE layer

Fusion-Task-Id: FN-3275
This commit is contained in:
Fusion
2026-05-03 09:16:29 -07:00
committed by gsxdsm
parent f2fa44e270
commit aecc2a7f4c
2 changed files with 43 additions and 1 deletions

View File

@@ -187,6 +187,32 @@ class MockEventSource {
}
}
function getMediaBlocks(css: string, mediaQuery: string): string[] {
const blocks: string[] = [];
let searchStart = 0;
while (searchStart < css.length) {
const start = css.indexOf(mediaQuery, searchStart);
if (start === -1) break;
const blockStart = css.indexOf("{", start);
if (blockStart === -1) break;
let depth = 1;
let cursor = blockStart + 1;
while (cursor < css.length && depth > 0) {
if (css[cursor] === "{") depth += 1;
else if (css[cursor] === "}") depth -= 1;
cursor += 1;
}
blocks.push(css.slice(start, cursor));
searchStart = cursor;
}
return blocks;
}
describe("PlanningModeModal", () => {
const mockOnClose = vi.fn();
const mockOnTaskCreated = vi.fn();
@@ -633,6 +659,17 @@ describe("PlanningModeModal", () => {
expect(blockMatch![0]).toContain("padding-inline-start: 0;");
expect(blockMatch![0]).toContain("justify-content: center;");
});
it("keeps mobile question view top spacing compact", async () => {
const { loadAllAppCss } = await import("../../test/cssFixture");
const css = loadAllAppCss();
const mobileBlocks = getMediaBlocks(css, "@media (max-width: 768px)");
const mobileCss = mobileBlocks.join("\n");
expect(mobileCss).toContain(".planning-question-scroll");
expect(mobileCss).toContain("padding-top: var(--space-sm);");
expect(mobileCss).toContain("gap: var(--space-md);");
});
});
describe("Planning flow", () => {