Files
paseo/packages/app/e2e/browser/provider-task-list.real.spec.ts
T
Mohamed BoudraandGitHub db6520bf36 Show live task progress while agents work (#3227)
* feat(agents): surface live task progress

Keep current task state above the composer and turn task snapshots into semantic timeline activity. Normalize provider task protocols while preserving genuine plan flows.

* fix(agents): admit tasks through stream sequencing

* test(agents): expect normalized task status
2026-08-11 18:23:30 +02:00

117 lines
4.4 KiB
TypeScript

import { mkdtempSync, realpathSync } from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import { expect, test } from "../support/fixtures";
import {
cleanupRewindFlow,
launchAgent,
sendMessage,
type AgentHandle,
type RewindFlowProvider,
} from "../support/helpers/rewind-flow";
import {
expectCompletedTaskActivity,
expectTaskListEntries,
openCompletedTaskList,
} from "../support/helpers/task-list";
import { submitMessage } from "../support/helpers/composer";
interface TaskScenario {
provider: RewindFlowProvider;
entries: [string, string];
prompt: string;
providerConfig?: Parameters<typeof launchAgent>[0]["providerConfig"];
}
const scenarios: TaskScenario[] = [
{
provider: "claude",
entries: ["Claude inventory alpha", "Claude inventory beta"],
providerConfig: { model: "opus" },
prompt:
"Use TaskCreate to create exactly two tasks named Claude inventory alpha and Claude inventory beta. Use TaskUpdate to mark each in_progress and then completed. Do not use subagents, shell commands, or edit files. Finish with TASKS_COMPLETE.",
},
{
provider: "codex",
entries: ["Codex inventory alpha", "Codex inventory beta"],
prompt:
"Use update_plan to track exactly two steps named Codex inventory alpha and Codex inventory beta. Move each through in_progress and completed. Do not use subagents, shell commands, or edit files. Finish with TASKS_COMPLETE.",
},
{
provider: "opencode",
entries: ["OpenCode inventory alpha", "OpenCode inventory beta"],
prompt:
"Use TodoWrite to track exactly two tasks named OpenCode inventory alpha and OpenCode inventory beta. Move each through in_progress and completed. Do not use subagents, shell commands, or edit files. Finish with TASKS_COMPLETE.",
},
];
test.describe("real provider composer task lists", () => {
test.setTimeout(600_000);
for (const scenario of scenarios) {
test(`${scenario.provider} shows native task progress above the composer`, async ({
page,
}, testInfo) => {
const cwd = realpathSync(
mkdtempSync(path.join(tmpdir(), `paseo-task-list-${scenario.provider}-`)),
);
let handle: AgentHandle | undefined;
try {
handle = await launchAgent({
page,
provider: scenario.provider,
cwd,
mode: "full-access",
providerConfig: scenario.providerConfig,
});
await sendMessage(handle, scenario.prompt);
await openCompletedTaskList(page, scenario.entries.length);
await expectTaskListEntries(page, scenario.entries);
await expectCompletedTaskActivity(page, scenario.entries);
await expect(page.getByText("TaskUpdate", { exact: true })).toHaveCount(0);
await expect(page.getByTestId("timeline-plan-card")).toHaveCount(0);
const screenshot = testInfo.outputPath(`${scenario.provider}-composer-tasks.png`);
await page.screenshot({ path: screenshot });
await testInfo.attach(`${scenario.provider} composer tasks`, {
path: screenshot,
contentType: "image/png",
});
} finally {
await cleanupRewindFlow({ handle, cwd });
}
});
}
test("Codex genuine Plan mode keeps the existing plan card", async ({ page }, testInfo) => {
const cwd = realpathSync(mkdtempSync(path.join(tmpdir(), "paseo-genuine-codex-plan-")));
let handle: AgentHandle | undefined;
try {
handle = await launchAgent({
page,
provider: "codex",
cwd,
mode: "full-access",
providerConfig: { featureValues: { plan_mode: true } },
});
await submitMessage(
page,
"Produce a concise implementation plan with exactly these steps: Inspect genuine plan boundary; Implement genuine plan boundary; Verify genuine plan boundary. Do not implement it.",
);
const planCard = page.getByTestId("permission-plan-card");
await expect(planCard).toBeVisible({ timeout: 120_000 });
await expect(planCard).toContainText("Inspect genuine plan boundary");
await expect(page.getByTestId("timeline-plan-card")).toHaveCount(0);
const screenshot = testInfo.outputPath("codex-genuine-plan.png");
await page.screenshot({ path: screenshot });
await testInfo.attach("Codex genuine plan", { path: screenshot, contentType: "image/png" });
} finally {
await cleanupRewindFlow({ handle, cwd });
}
});
});