feat: publish Agent Studio integrations and setup guide

This commit is contained in:
Wenxin Duan
2026-09-16 16:32:16 +08:00
parent 2ad089d68a
commit 05e6060490
106 changed files with 4942 additions and 198 deletions
+36
View File
@@ -9,6 +9,42 @@ const task = { id, title: "Window", prompt: "Turn naturally toward the window; a
afterEach(() => { vi.unstubAllGlobals(); vi.useRealTimers(); });
describe("image video UI", () => {
it("continues the exact task only after confirmation and never sends or generates automatically", async () => {
const onDraft = vi.fn(); const requests: { url: string; body: unknown }[] = [];
const pending = { ...task, state: "awaiting_submission", revision: 9 };
vi.stubGlobal("fetch", (url: string, init?: RequestInit) => {
if (init?.method === "POST") requests.push({ url, body: init.body });
return Promise.resolve(new Response(JSON.stringify(init?.method === "POST" ? { task: { ...pending, revision: 10 } } : { tasks: [pending] })));
});
render(<ImageVideoPanel sessionId="ses_new" onDraft={onDraft} />);
const user = userEvent.setup();
await user.click(await screen.findByRole("button", { name: "继续此任务" }));
expect(screen.getByRole("button", { name: "确认接续(不生成)" })).toBeDisabled();
expect(requests).toEqual([]);
await user.click(screen.getByRole("checkbox", { name: /确认将此任务接续到当前会话/ }));
await user.click(screen.getByRole("button", { name: "确认接续(不生成)" }));
await waitFor(() => expect(onDraft).toHaveBeenCalledWith(expect.objectContaining({ id, state: "awaiting_submission", revision: 10 })));
expect(requests).toEqual([{ url: `/api/sessions/ses_new/image-video/tasks/${id}/continue`, body: JSON.stringify({ confirmed: true, expectedRevision: 9 }) }]);
});
it("does not offer continuation for unknown submission/upload outcomes", async () => {
vi.stubGlobal("fetch", () => Promise.resolve(new Response(JSON.stringify({ tasks: [{ ...task, revision: 2, state: "unknown_upload" }] }))));
render(<ImageVideoPanel sessionId="ses_new" onDraft={vi.fn()} />);
expect(await screen.findByText(/上传状态未知/)).toBeVisible();
expect(screen.queryByRole("button", { name: "继续此任务" })).not.toBeInTheDocument();
});
it("ignores a late continuation response after switching sessions", async () => {
const onDraft = vi.fn(); const pending = { ...task, revision: 9, state: "awaiting_submission" };
let finish!: (response: Response) => void;
vi.stubGlobal("fetch", (_url: string, init?: RequestInit) => init?.method === "POST" ? new Promise<Response>(resolve => { finish = resolve; }) : Promise.resolve(new Response(JSON.stringify({ tasks: [pending] }))));
const view = render(<ImageVideoPanel sessionId="ses_old" onDraft={onDraft} />); const user = userEvent.setup();
await user.click(await screen.findByRole("button", { name: "继续此任务" }));
await user.click(screen.getByRole("checkbox", { name: /确认将此任务接续到当前会话/ }));
await user.click(screen.getByRole("button", { name: "确认接续(不生成)" }));
view.rerender(<ImageVideoPanel sessionId="ses_new" onDraft={onDraft} />);
await act(() => { finish(new Response(JSON.stringify({ task: pending }))); return Promise.resolve(); });
expect(onDraft).not.toHaveBeenCalled();
expect(screen.getByRole("button", { name: "继续此任务" })).toBeEnabled();
});
it("restores queued tasks, polls at 30 seconds, and cleans up after unmount", async () => {
vi.useFakeTimers();
const fetcher = vi.fn(() => Promise.resolve(new Response(JSON.stringify({ tasks: [task] }))));