feat: land page aggregate and phase7 document ai mainline

- 收口 page aggregate 读取、本地状态与命令客户端\n- 接入 phase7 document ai sidecar 与前端编排入口\n- 更新 architecture 与 design 状态迁移
This commit is contained in:
lix-2026
2026-04-23 07:38:34 +08:00
parent 8353aea2f9
commit 41e958769e
93 changed files with 8778 additions and 2222 deletions
@@ -1,11 +1,21 @@
import { documentBridgeErrorResponse } from "@/lib/documents/bridge";
import { getAuthedConvexClient } from "@/lib/convex/route";
import {
buildMnoteWebForwardHeaders,
buildMnoteWebStreamUrl,
} from "@/lib/server/mnote-web";
buildDocumentBridgeContext,
buildDocumentQueryEnvelope,
documentBridgeErrorResponse,
} from "@/lib/documents/bridge";
import {
executeRustBridgeQueryTransport,
resolveRustBridgeQueryPlan,
} from "@/lib/documents/rust-runtime";
import { mapSidebarDatasetListQueryResultToInitialData } from "@/lib/sidebar-data";
export const dynamic = "force-dynamic";
function toSseFrame(event: string, data: unknown) {
return `event: ${event}\ndata: ${JSON.stringify(data ?? null)}\n\n`;
}
export async function GET(request: Request) {
try {
const requestUrl = new URL(request.url);
@@ -16,26 +26,73 @@ export async function GET(request: Request) {
return Response.json({ error: "缺少 workspaceId" }, { status: 400 });
}
const targetUrl = buildMnoteWebStreamUrl({ workspaceId, cursor });
const headers = await buildMnoteWebForwardHeaders(request);
headers.set("accept", "text/event-stream");
headers.set("x-mnote-workspace-id", workspaceId);
const upstream = await fetch(targetUrl.toString(), {
method: "GET",
headers,
cache: "no-store",
redirect: "follow",
const { client } = await getAuthedConvexClient();
const context = await buildDocumentBridgeContext({
request,
workspaceId,
});
const responseHeaders = new Headers(upstream.headers);
responseHeaders.delete("set-cookie");
responseHeaders.set("cache-control", "no-store");
const sidebarEnvelope = buildDocumentQueryEnvelope({
name: "sidebar.dataset.list",
payload: {
workspaceId,
},
});
const sidebarPlan = await resolveRustBridgeQueryPlan({
context,
envelope: sidebarEnvelope,
});
const sidebarDataset = await executeRustBridgeQueryTransport({
client,
plan: sidebarPlan,
});
return new Response(upstream.body, {
status: upstream.status,
statusText: upstream.statusText,
headers: responseHeaders,
const overviewEnvelope = buildDocumentQueryEnvelope({
name: "bridge.workspace.overview",
payload: {
workspaceId,
limit: 20,
cursor,
commandStatus: null,
eventStatus: null,
targetPageId: null,
targetBlockId: null,
aggregateType: null,
aggregateId: null,
},
});
const overviewPlan = await resolveRustBridgeQueryPlan({
context,
envelope: overviewEnvelope,
});
const overview = await executeRustBridgeQueryTransport({
client,
plan: overviewPlan,
});
const payload = {
kind: "snapshot",
stream: "workspace",
projection: "sidebar_tree",
workspaceId,
rootNodeId: null,
cursor,
requestId: context.requestId,
traceId: context.traceId,
data: mapSidebarDatasetListQueryResultToInitialData(sidebarDataset),
snapshot: {
dataset: sidebarDataset,
tree: sidebarDataset.kernel_sidebar_projection ?? sidebarDataset.kernelSidebarProjection ?? null,
},
overview,
};
return new Response(toSseFrame("snapshot", payload), {
status: 200,
headers: {
"content-type": "text/event-stream; charset=utf-8",
"cache-control": "no-store",
},
});
} catch (error) {
return documentBridgeErrorResponse(error);