import { afterEach, expect, it, vi } from "vitest"; import { createAgentApiClient } from "./client"; afterEach(() => vi.unstubAllGlobals()); it("reads mailbox pages without sending or consuming messages and validates the contract", async () => { const message = { message_id: "m1", task_id: "t1", run_id: "r1", source_session_id: "task-session", target_session_id: "chat-session", direction: "to_chat", text: "现场记录已核对", status: "pending", in_reply_to: null, created_at: "2026-10-13T00:00:00Z", source_owner_id: "private-owner" }; const fetchMock = vi.fn().mockResolvedValue(Response.json({ items: [message], next_cursor: "m1" })); vi.stubGlobal("fetch", fetchMock); const client = createAgentApiClient("http://agent.local", { getAccessToken: async () => "token", getProjectId: async () => "p1" }); const page = await client.listAgentMessages("chat-session", { cursor: "previous" }); expect(page.items[0]).not.toHaveProperty("source_owner_id"); const [url, init] = fetchMock.mock.calls[0]; expect(url).toBe("http://agent.local/api/v1/session/chat-session/agent-messages?limit=50&cursor=previous"); expect(init.method).toBeUndefined(); expect(init.body).toBeUndefined(); expect(new Headers(init.headers).get("X-Project-Id")).toBe("p1"); fetchMock.mockResolvedValue(Response.json({ items: [{ ...message, target_session_id: null, direction: "to_task" }], next_cursor: null })); expect((await client.listAgentMessages("chat-session")).items[0].target_session_id).toBeNull(); fetchMock.mockResolvedValue(Response.json({ items: [{ ...message, status: "invented" }], next_cursor: null })); await expect(client.listAgentMessages("chat-session")).rejects.toThrow(); }); it("accepts inbox notifications only for the subscribed session", async () => { vi.stubGlobal("fetch", vi.fn().mockResolvedValue(new Response([ 'event: agent_message\ndata: {"session_id":"other"}\n\n', 'event: agent_message\ndata: {"session_id":"main"}\n\n', ': heartbeat\n\n' ].join("")))); const onMessage = vi.fn(); await createAgentApiClient("http://agent.local").streamAgentMessages("main", { onMessage }); expect(onMessage).toHaveBeenCalledOnce(); });