import { describe, expect, it, vi } from "vitest"; import { streamTreeFrames } from "./server"; import type { TreeStreamCommandLogCursorRow } from "./server"; function buildOverview(rows: TreeStreamCommandLogCursorRow[]) { return { command_logs: rows, domain_events: [], has_more: false, next_cursor: null, generated_at: "2026-04-24T00:00:00Z", }; } async function collectFrames(generator: AsyncGenerator) { const frames: T[] = []; for await (const frame of generator) { frames.push(frame); } return frames; } describe("tree-stream/server", () => { it("workspace scope 首帧应发 snapshot,并固定 sidebar_tree + cursor", async () => { const frames = await collectFrames( streamTreeFrames({ workspaceId: "ws_1", pollMs: 1, maxPolls: 0, loadOverview: vi.fn().mockResolvedValue( buildOverview([{ id: "clog_2", created_at: "2026-04-24T00:00:01Z" }]), ), loadSnapshot: vi.fn().mockResolvedValue({ requestId: "req_1", traceId: "trace_1", data: { activeWorkspaceId: "ws_1", documents: [] }, snapshot: { dataset: { active_workspace_id: "ws_1", documents: [] }, tree: { items: [] } }, }), sleep: vi.fn().mockResolvedValue(undefined), }), ); expect(frames).toHaveLength(1); expect(frames[0]).toMatchObject({ event: "snapshot", payload: { kind: "snapshot", stream: "workspace", workspaceId: "ws_1", rootNodeId: null, projection: "sidebar_tree", cursor: JSON.stringify({ createdAt: "2026-04-24T00:00:01Z", id: "clog_2", }), }, }); }); it("subtree scope 首帧应切到 subtree + page_tree", async () => { const frames = await collectFrames( streamTreeFrames({ workspaceId: "ws_1", rootNodeId: "page_root", pollMs: 1, maxPolls: 0, loadOverview: vi.fn().mockResolvedValue( buildOverview([{ id: "clog_2", created_at: "2026-04-24T00:00:01Z" }]), ), loadSnapshot: vi.fn().mockResolvedValue({ requestId: "req_subtree_1", traceId: "trace_subtree_1", data: { nodes: [] }, snapshot: { dataset: { active_workspace_id: "ws_1", documents: [] }, tree: { nodes: [] } }, }), sleep: vi.fn().mockResolvedValue(undefined), }), ); expect(frames).toHaveLength(1); expect(frames[0]).toMatchObject({ event: "snapshot", payload: { kind: "snapshot", stream: "subtree", workspaceId: "ws_1", rootNodeId: "page_root", projection: "page_tree", }, }); }); it("检测到 cursor 之后出现新命令时,应发 resync 而不是静默结束", async () => { const loadOverview = vi .fn() .mockResolvedValueOnce( buildOverview([{ id: "clog_1", created_at: "2026-04-24T00:00:01Z" }]), ) .mockResolvedValueOnce( buildOverview([ { id: "clog_2", created_at: "2026-04-24T00:00:02Z" }, { id: "clog_1", created_at: "2026-04-24T00:00:01Z" }, ]), ); const loadSnapshot = vi .fn() .mockResolvedValueOnce({ requestId: "req_1", traceId: "trace_1", data: { activeWorkspaceId: "ws_1", documents: [{ id: "page_1" }] }, snapshot: { dataset: { active_workspace_id: "ws_1", documents: [{ id: "page_1" }] }, tree: { items: [] } }, }) .mockResolvedValueOnce({ requestId: "req_2", traceId: "trace_2", data: { activeWorkspaceId: "ws_1", documents: [{ id: "page_1" }, { id: "page_2" }] }, snapshot: { dataset: { active_workspace_id: "ws_1", documents: [{ id: "page_1" }, { id: "page_2" }] }, tree: { items: [] }, }, }); const frames = await collectFrames( streamTreeFrames({ workspaceId: "ws_1", pollMs: 1, maxPolls: 1, loadOverview, loadSnapshot, sleep: vi.fn().mockResolvedValue(undefined), }), ); expect(frames).toHaveLength(2); expect(frames[0]).toMatchObject({ event: "snapshot" }); expect(frames[1]).toMatchObject({ event: "resync", payload: { kind: "resync", stream: "workspace", workspaceId: "ws_1", projection: "sidebar_tree", cursor: JSON.stringify({ createdAt: "2026-04-24T00:00:02Z", id: "clog_2", }), }, }); expect(loadSnapshot).toHaveBeenCalledTimes(2); }); it("检测到带 streamDelta 的单条新命令时,应直接发 delta", async () => { const loadOverview = vi .fn() .mockResolvedValueOnce( buildOverview([{ id: "clog_1", created_at: "2026-04-24T00:00:01Z" }]), ) .mockResolvedValueOnce( buildOverview([ { id: "clog_2", created_at: "2026-04-24T00:00:02Z", command_name: "tree.node.archive", payload: { documentId: "page_2", streamDelta: { op: "remove_document", documentId: "page_2", }, }, }, { id: "clog_1", created_at: "2026-04-24T00:00:01Z" }, ]), ); const loadSnapshot = vi.fn().mockResolvedValue({ requestId: "req_1", traceId: "trace_1", data: { activeWorkspaceId: "ws_1", documents: [{ id: "page_1" }] }, snapshot: { dataset: { active_workspace_id: "ws_1", documents: [{ id: "page_1" }] }, tree: { items: [] } }, }); const frames = await collectFrames( streamTreeFrames({ workspaceId: "ws_1", pollMs: 1, maxPolls: 1, loadOverview, loadSnapshot, sleep: vi.fn().mockResolvedValue(undefined), }), ); expect(frames).toHaveLength(2); expect(frames[1]).toMatchObject({ event: "delta", payload: { kind: "delta", cursor: JSON.stringify({ createdAt: "2026-04-24T00:00:02Z", id: "clog_2", }), data: { op: "remove_document", documentId: "page_2", }, }, }); expect(loadSnapshot).toHaveBeenCalledTimes(1); }); it("只有 domain event 推进时,也应刷新 cursor 并触发 resync", async () => { const loadOverview = vi .fn() .mockResolvedValueOnce( buildOverview([{ id: "clog_1", created_at: "2026-04-24T00:00:01Z" }]), ) .mockResolvedValueOnce({ command_logs: [{ id: "clog_1", created_at: "2026-04-24T00:00:01Z" }], domain_events: [ { event_id: "evt_2", created_at: "2026-04-24T00:00:02Z", }, ], has_more: false, next_cursor: null, generated_at: "2026-04-24T00:00:02Z", }); const loadSnapshot = vi .fn() .mockResolvedValueOnce({ requestId: "req_1", traceId: "trace_1", data: { activeWorkspaceId: "ws_1", documents: [{ id: "page_1" }] }, snapshot: { dataset: { active_workspace_id: "ws_1", documents: [{ id: "page_1" }] }, tree: { items: [] } }, }) .mockResolvedValueOnce({ requestId: "req_2", traceId: "trace_2", data: { activeWorkspaceId: "ws_1", documents: [{ id: "page_1" }] }, snapshot: { dataset: { active_workspace_id: "ws_1", documents: [{ id: "page_1" }] }, tree: { items: [] } }, }); const frames = await collectFrames( streamTreeFrames({ workspaceId: "ws_1", pollMs: 1, maxPolls: 1, loadOverview, loadSnapshot, sleep: vi.fn().mockResolvedValue(undefined), }), ); expect(frames).toHaveLength(2); expect(frames[1]).toMatchObject({ event: "resync", payload: { kind: "resync", cursor: JSON.stringify({ createdAt: "2026-04-24T00:00:02Z", id: "domain_event:evt_2", }), }, }); expect(loadSnapshot).toHaveBeenCalledTimes(2); }); it("单条新 domain event 携带 streamDelta 时,应直接发 delta", async () => { const loadOverview = vi .fn() .mockResolvedValueOnce({ command_logs: [], domain_events: [ { event_id: "evt_1", created_at: "2026-04-24T00:00:01Z", }, ], has_more: false, next_cursor: null, generated_at: "2026-04-24T00:00:01Z", }) .mockResolvedValueOnce({ command_logs: [], domain_events: [ { event_id: "evt_2", created_at: "2026-04-24T00:00:02Z", payload: { command_name: "tree.node.rename", streamDelta: { op: "upsert_document", document: { id: "page_2", title: "新标题", }, }, }, }, { event_id: "evt_1", created_at: "2026-04-24T00:00:01Z", }, ], has_more: false, next_cursor: null, generated_at: "2026-04-24T00:00:02Z", }); const loadSnapshot = vi.fn().mockResolvedValue({ requestId: "req_1", traceId: "trace_1", data: { activeWorkspaceId: "ws_1", documents: [{ id: "page_1" }] }, snapshot: { dataset: { active_workspace_id: "ws_1", documents: [{ id: "page_1" }] }, tree: { items: [] } }, }); const frames = await collectFrames( streamTreeFrames({ workspaceId: "ws_1", pollMs: 1, maxPolls: 1, loadOverview, loadSnapshot, sleep: vi.fn().mockResolvedValue(undefined), }), ); expect(frames).toHaveLength(2); expect(frames[1]).toMatchObject({ event: "delta", payload: { kind: "delta", cursor: JSON.stringify({ createdAt: "2026-04-24T00:00:02Z", id: "domain_event:evt_2", }), data: { op: "upsert_document", document: { id: "page_2", title: "新标题", }, }, }, }); expect(loadSnapshot).toHaveBeenCalledTimes(1); }); it("单条资源 domain event 携带 upsert_assets 时,应直接发 delta", async () => { const streamDelta = { op: "upsert_assets", upsertAssets: [ { id: "asset_1", workspace_id: "ws_1", document_id: "doc_target", asset_type: "file", file_url: "/file.pdf", thumbnail_url: "/file.pdf", file_name: "file.pdf", file_size: 1024, mime_type: "application/pdf", created_at: "2026-04-26T00:00:00Z", updated_at: "2026-04-26T00:00:00Z", }, ], }; const loadOverview = vi .fn() .mockResolvedValueOnce({ command_logs: [], domain_events: [ { event_id: "evt_1", created_at: "2026-04-24T00:00:01Z", }, ], has_more: false, next_cursor: null, generated_at: "2026-04-24T00:00:01Z", }) .mockResolvedValueOnce({ command_logs: [], domain_events: [ { event_id: "evt_2", created_at: "2026-04-24T00:00:02Z", payload: { schema: "mnote.tree.domain_event", eventType: "tree.resource.moved", streamDelta, }, }, { event_id: "evt_1", created_at: "2026-04-24T00:00:01Z", }, ], has_more: false, next_cursor: null, generated_at: "2026-04-24T00:00:02Z", }); const loadSnapshot = vi.fn().mockResolvedValue({ requestId: "req_1", traceId: "trace_1", data: { activeWorkspaceId: "ws_1", documents: [{ id: "page_1" }] }, snapshot: { dataset: { active_workspace_id: "ws_1", documents: [{ id: "page_1" }] }, tree: { items: [] } }, }); const frames = await collectFrames( streamTreeFrames({ workspaceId: "ws_1", pollMs: 1, maxPolls: 1, loadOverview, loadSnapshot, sleep: vi.fn().mockResolvedValue(undefined), }), ); expect(frames).toHaveLength(2); expect(frames[1]).toMatchObject({ event: "delta", payload: { kind: "delta", data: streamDelta, }, }); expect(loadSnapshot).toHaveBeenCalledTimes(1); }); it("单条新 domain event 缺少可识别 streamDelta 时,应保守回退 resync", async () => { const loadOverview = vi .fn() .mockResolvedValueOnce({ command_logs: [], domain_events: [ { event_id: "evt_1", created_at: "2026-04-24T00:00:01Z", }, ], has_more: false, next_cursor: null, generated_at: "2026-04-24T00:00:01Z", }) .mockResolvedValueOnce({ command_logs: [], domain_events: [ { event_id: "evt_2", created_at: "2026-04-24T00:00:02Z", payload: { schema: "mnote.tree.domain_event", schemaVersion: 1, eventType: "tree.node.unknown", }, }, { event_id: "evt_1", created_at: "2026-04-24T00:00:01Z", }, ], has_more: false, next_cursor: null, generated_at: "2026-04-24T00:00:02Z", }); const loadSnapshot = vi .fn() .mockResolvedValueOnce({ requestId: "req_1", traceId: "trace_1", data: { activeWorkspaceId: "ws_1", documents: [{ id: "page_1" }] }, snapshot: { dataset: { active_workspace_id: "ws_1", documents: [{ id: "page_1" }] }, tree: { items: [] } }, }) .mockResolvedValueOnce({ requestId: "req_2", traceId: "trace_2", data: { activeWorkspaceId: "ws_1", documents: [{ id: "page_2" }] }, snapshot: { dataset: { active_workspace_id: "ws_1", documents: [{ id: "page_2" }] }, tree: { items: [] } }, }); const frames = await collectFrames( streamTreeFrames({ workspaceId: "ws_1", pollMs: 1, maxPolls: 1, loadOverview, loadSnapshot, sleep: vi.fn().mockResolvedValue(undefined), }), ); expect(frames).toHaveLength(2); expect(frames[1]).toMatchObject({ event: "resync", payload: { kind: "resync", cursor: JSON.stringify({ createdAt: "2026-04-24T00:00:02Z", id: "domain_event:evt_2", }), }, }); expect(loadSnapshot).toHaveBeenCalledTimes(2); }); it("同一命令的 command log 与 domain event 同时推进且 delta 一致时,应发一次 delta", async () => { const streamDelta = { op: "upsert_document", document: { id: "page_2", title: "同一标题" }, }; const loadOverview = vi .fn() .mockResolvedValueOnce( buildOverview([{ id: "clog_1", command_id: "cmd_1", created_at: "2026-04-24T00:00:01Z" }]), ) .mockResolvedValueOnce({ command_logs: [ { id: "clog_2", command_id: "cmd_2", created_at: "2026-04-24T00:00:02Z", command_name: "tree.node.rename", payload: { streamDelta }, }, { id: "clog_1", command_id: "cmd_1", created_at: "2026-04-24T00:00:01Z" }, ], domain_events: [ { event_id: "evt_2", command_id: "cmd_2", created_at: "2026-04-24T00:00:02Z", payload: { streamDelta }, }, ], has_more: false, next_cursor: null, generated_at: "2026-04-24T00:00:02Z", }); const loadSnapshot = vi.fn().mockResolvedValue({ requestId: "req_1", traceId: "trace_1", data: { activeWorkspaceId: "ws_1", documents: [{ id: "page_1" }] }, snapshot: { dataset: { active_workspace_id: "ws_1", documents: [{ id: "page_1" }] }, tree: { items: [] } }, }); const frames = await collectFrames( streamTreeFrames({ workspaceId: "ws_1", pollMs: 1, maxPolls: 1, loadOverview, loadSnapshot, sleep: vi.fn().mockResolvedValue(undefined), }), ); expect(frames).toHaveLength(2); expect(frames[1]).toMatchObject({ event: "delta", payload: { kind: "delta", cursor: JSON.stringify({ createdAt: "2026-04-24T00:00:02Z", id: "clog_2", }), data: streamDelta, }, }); expect(loadSnapshot).toHaveBeenCalledTimes(1); }); it("上一帧 cursor 来自 command log 时,应按时间排除旧 domain event 后再做双写去重", async () => { const streamDelta = { op: "move_document", documentId: "page_2", parentId: "page_1", sortOrder: 2, }; const loadOverview = vi .fn() .mockResolvedValueOnce( buildOverview([{ id: "clog_1", command_id: "cmd_1", created_at: "2026-04-24T00:00:01Z" }]), ) .mockResolvedValueOnce({ command_logs: [ { id: "clog_2", command_id: "cmd_2", created_at: "2026-04-24T00:00:02Z", command_name: "tree.subtree.move", payload: { streamDelta }, }, { id: "clog_1", command_id: "cmd_1", created_at: "2026-04-24T00:00:01Z" }, ], domain_events: [ { event_id: "evt_2", command_id: "cmd_2", created_at: "2026-04-24T00:00:02Z", payload: { streamDelta }, }, { event_id: "evt_1", command_id: "cmd_1", created_at: "2026-04-24T00:00:01Z", payload: { streamDelta: { op: "noop", }, }, }, ], has_more: false, next_cursor: null, generated_at: "2026-04-24T00:00:02Z", }); const loadSnapshot = vi.fn().mockResolvedValue({ requestId: "req_1", traceId: "trace_1", data: { activeWorkspaceId: "ws_1", documents: [{ id: "page_1" }] }, snapshot: { dataset: { active_workspace_id: "ws_1", documents: [{ id: "page_1" }] }, tree: { items: [] } }, }); const frames = await collectFrames( streamTreeFrames({ workspaceId: "ws_1", pollMs: 1, maxPolls: 1, loadOverview, loadSnapshot, sleep: vi.fn().mockResolvedValue(undefined), }), ); expect(frames).toHaveLength(2); expect(frames[1]).toMatchObject({ event: "delta", payload: { kind: "delta", data: streamDelta, }, }); expect(loadSnapshot).toHaveBeenCalledTimes(1); }); it("command log 与 domain event 同时推进且 delta 不一致时,应回退 resync 避免漏发", async () => { const loadOverview = vi .fn() .mockResolvedValueOnce( buildOverview([{ id: "clog_1", created_at: "2026-04-24T00:00:01Z" }]), ) .mockResolvedValueOnce({ command_logs: [ { id: "clog_2", created_at: "2026-04-24T00:00:03Z", command_name: "tree.node.rename", payload: { streamDelta: { op: "upsert_document", document: { id: "page_2", title: "命令标题" }, }, }, }, { id: "clog_1", created_at: "2026-04-24T00:00:01Z" }, ], domain_events: [ { event_id: "evt_2", created_at: "2026-04-24T00:00:02Z", payload: { streamDelta: { op: "remove_document", documentId: "page_3", }, }, }, ], has_more: false, next_cursor: null, generated_at: "2026-04-24T00:00:03Z", }); const loadSnapshot = vi .fn() .mockResolvedValueOnce({ requestId: "req_1", traceId: "trace_1", data: { activeWorkspaceId: "ws_1", documents: [{ id: "page_1" }] }, snapshot: { dataset: { active_workspace_id: "ws_1", documents: [{ id: "page_1" }] }, tree: { items: [] } }, }) .mockResolvedValueOnce({ requestId: "req_2", traceId: "trace_2", data: { activeWorkspaceId: "ws_1", documents: [{ id: "page_2" }] }, snapshot: { dataset: { active_workspace_id: "ws_1", documents: [{ id: "page_2" }] }, tree: { items: [] } }, }); const frames = await collectFrames( streamTreeFrames({ workspaceId: "ws_1", pollMs: 1, maxPolls: 1, loadOverview, loadSnapshot, sleep: vi.fn().mockResolvedValue(undefined), }), ); expect(frames).toHaveLength(2); expect(frames[1]).toMatchObject({ event: "resync", payload: { kind: "resync", }, }); expect(loadSnapshot).toHaveBeenCalledTimes(2); }); it("单条新命令缺少可稳定解释的 streamDelta 时,应回退 resync", async () => { const loadOverview = vi .fn() .mockResolvedValueOnce( buildOverview([{ id: "clog_1", created_at: "2026-04-24T00:00:01Z" }]), ) .mockResolvedValueOnce( buildOverview([ { id: "clog_2", created_at: "2026-04-24T00:00:02Z", command_name: "tree.subtree.move", payload: { documentId: "page_2", }, }, { id: "clog_1", created_at: "2026-04-24T00:00:01Z" }, ]), ); const loadSnapshot = vi .fn() .mockResolvedValueOnce({ requestId: "req_1", traceId: "trace_1", data: { activeWorkspaceId: "ws_1", documents: [{ id: "page_1" }] }, snapshot: { dataset: { active_workspace_id: "ws_1", documents: [{ id: "page_1" }] }, tree: { items: [] } }, }) .mockResolvedValueOnce({ requestId: "req_2", traceId: "trace_2", data: { activeWorkspaceId: "ws_1", documents: [{ id: "page_1" }, { id: "page_2" }] }, snapshot: { dataset: { active_workspace_id: "ws_1", documents: [{ id: "page_1" }, { id: "page_2" }] }, tree: { items: [] }, }, }); const frames = await collectFrames( streamTreeFrames({ workspaceId: "ws_1", pollMs: 1, maxPolls: 1, loadOverview, loadSnapshot, sleep: vi.fn().mockResolvedValue(undefined), }), ); expect(frames).toHaveLength(2); expect(frames[1]).toMatchObject({ event: "resync", payload: { kind: "resync", }, }); expect(loadSnapshot).toHaveBeenCalledTimes(2); }); it("正文保存这类无树结构影响的命令应降级为 noop delta,而不是触发 resync", async () => { const loadOverview = vi .fn() .mockResolvedValueOnce( buildOverview([{ id: "clog_1", created_at: "2026-04-24T00:00:01Z" }]), ) .mockResolvedValueOnce( buildOverview([ { id: "clog_2", created_at: "2026-04-24T00:00:02Z", command_name: "page.body.save", payload: { documentId: "page_1", }, }, { id: "clog_1", created_at: "2026-04-24T00:00:01Z" }, ]), ); const loadSnapshot = vi.fn().mockResolvedValue({ requestId: "req_1", traceId: "trace_1", data: { activeWorkspaceId: "ws_1", documents: [{ id: "page_1" }] }, snapshot: { dataset: { active_workspace_id: "ws_1", documents: [{ id: "page_1" }] }, tree: { items: [] } }, }); const frames = await collectFrames( streamTreeFrames({ workspaceId: "ws_1", pollMs: 1, maxPolls: 1, loadOverview, loadSnapshot, sleep: vi.fn().mockResolvedValue(undefined), }), ); expect(frames).toHaveLength(2); expect(frames[1]).toMatchObject({ event: "delta", payload: { kind: "delta", data: { op: "noop", }, }, }); expect(loadSnapshot).toHaveBeenCalledTimes(1); }); it("move 这类附带 move_document 的新命令应直接发 delta,而不是触发 resync", async () => { const sidebarSnapshot = { activeWorkspaceId: "ws_1", workspaces: [], documents: [ { id: "page_1", workspace_id: "ws_1", title: "页面 1", parent_id: null, sort_order: 0, access_scope: "private", is_starred: false, is_template: false, created_at: "2026-04-24T00:00:00Z", updated_at: "2026-04-24T00:01:00Z", }, ], kernelSidebarProjection: { projectionId: "kernel_projection:sidebar_tree:workspace_root", projection: "sidebar_tree", rootNodeId: null, items: [], edges: [], }, kernelFileTreeProjection: { projectionId: "kernel_projection:file_tree:workspace_root", projection: "file_tree", rootNodeId: null, items: [], edges: [], }, kernelSidebarTree: [], trashedDocuments: [], mediaAssets: [], mindmapDocs: [], mindmapAssets: [], mindmapAssetChildren: {}, tableAssets: [], }; const loadOverview = vi .fn() .mockResolvedValueOnce( buildOverview([{ id: "clog_1", created_at: "2026-04-24T00:00:01Z" }]), ) .mockResolvedValueOnce( buildOverview([ { id: "clog_2", created_at: "2026-04-24T00:00:02Z", command_name: "tree.subtree.move", payload: { documentId: "page_1", streamDelta: { op: "move_document", documentId: "page_1", parentId: null, sortOrder: 0, updatedAt: "2026-04-24T00:01:00Z", }, }, }, { id: "clog_1", created_at: "2026-04-24T00:00:01Z" }, ]), ); const loadSnapshot = vi.fn().mockResolvedValue({ requestId: "req_1", traceId: "trace_1", data: { activeWorkspaceId: "ws_1", documents: [] }, snapshot: { dataset: { active_workspace_id: "ws_1", documents: [] }, tree: { items: [] } }, }); const frames = await collectFrames( streamTreeFrames({ workspaceId: "ws_1", pollMs: 1, maxPolls: 1, loadOverview, loadSnapshot, sleep: vi.fn().mockResolvedValue(undefined), }), ); expect(frames).toHaveLength(2); expect(frames[1]).toMatchObject({ event: "delta", payload: { kind: "delta", data: { op: "move_document", documentId: "page_1", parentId: null, sortOrder: 0, updatedAt: "2026-04-24T00:01:00Z", }, }, }); expect(loadSnapshot).toHaveBeenCalledTimes(1); }); it("copy 这类附带 upsert_documents 的新命令应保留批量文档字段", async () => { const loadOverview = vi .fn() .mockResolvedValueOnce( buildOverview([{ id: "clog_1", created_at: "2026-04-24T00:00:01Z" }]), ) .mockResolvedValueOnce( buildOverview([ { id: "clog_2", created_at: "2026-04-24T00:00:02Z", command_name: "tree.subtree.copy", payload: { streamDelta: { op: "upsert_documents", upsertDocuments: [ { id: "copy_1", workspace_id: "ws_1", title: "Copy", parent_id: null, sort_order: 2, is_starred: false, access_scope: "private", is_template: false, created_at: "2026-04-24T00:00:02Z", updated_at: "2026-04-24T00:00:02Z", }, ], }, }, }, { id: "clog_1", created_at: "2026-04-24T00:00:01Z" }, ]), ); const loadSnapshot = vi.fn().mockResolvedValue({ requestId: "req_1", traceId: "trace_1", data: { activeWorkspaceId: "ws_1", documents: [] }, snapshot: { dataset: { active_workspace_id: "ws_1", documents: [] }, tree: { items: [] } }, }); const frames = await collectFrames( streamTreeFrames({ workspaceId: "ws_1", pollMs: 1, maxPolls: 1, loadOverview, loadSnapshot, sleep: vi.fn().mockResolvedValue(undefined), }), ); expect(frames[1]).toMatchObject({ event: "delta", payload: { kind: "delta", data: { op: "upsert_documents", upsertDocuments: [ expect.objectContaining({ id: "copy_1", workspace_id: "ws_1", }), ], }, }, }); expect(loadSnapshot).toHaveBeenCalledTimes(1); }); it("轮询期间没有新 cursor 时,不应额外发 resync", async () => { const loadOverview = vi .fn() .mockResolvedValue(buildOverview([{ id: "clog_1", created_at: "2026-04-24T00:00:01Z" }])); const frames = await collectFrames( streamTreeFrames({ workspaceId: "ws_1", pollMs: 1, maxPolls: 1, loadOverview, loadSnapshot: vi.fn().mockResolvedValue({ requestId: "req_1", traceId: "trace_1", data: { activeWorkspaceId: "ws_1", documents: [] }, snapshot: { dataset: { active_workspace_id: "ws_1", documents: [] }, tree: { items: [] } }, }), sleep: vi.fn().mockResolvedValue(undefined), }), ); expect(frames).toHaveLength(1); expect(frames[0]).toMatchObject({ event: "snapshot" }); }); });