feat: 收口文档桥接与 OnlyOffice/Sidebar 回归

- 为 documents.save/meta/content、blocks.patch 与 sidebar.dataset.list 补齐 Rust 协议映射、共享契约与桥接执行器

- 对齐 BlockNote、Mindmap、OnlyOffice 的保存/路由元信息,并补真实浏览器回归脚本与 OnlyOffice 部署基线

- 忽略 Rust 本地构建产物与 Harness 调试状态文件,避免临时产物进入仓库历史
This commit is contained in:
lix-2026
2026-04-15 03:06:29 +08:00
parent 84a8454fa9
commit b33ffb99e7
51 changed files with 3260 additions and 379 deletions
@@ -2,6 +2,8 @@
// 宿主页面通过 postMessage 下发 oo_* 工具调用;插件执行后再 postMessage 回传结果。
(function () {
const CHANNEL = "mnote_onlyoffice_agent_tools_v1";
let readyPulseTimer = null;
let readyPulseDeadline = 0;
const safePostToTop = (payload) => {
try {
@@ -13,6 +15,50 @@
}
};
const isPluginApiReady = () =>
Boolean(window.Asc && window.Asc.plugin && typeof window.Asc.plugin.executeMethod === "function");
const stopReadyPulse = () => {
if (readyPulseTimer) {
window.clearInterval(readyPulseTimer);
readyPulseTimer = null;
}
readyPulseDeadline = 0;
};
const startReadyPulse = () => {
if (readyPulseTimer) return;
readyPulseDeadline = Date.now() + 20_000;
safePostToTop({ type: "ready" });
readyPulseTimer = window.setInterval(() => {
if (Date.now() > readyPulseDeadline) {
stopReadyPulse();
return;
}
safePostToTop({ type: "ready" });
}, 1000);
};
const waitForPluginApiReady = () => {
if (isPluginApiReady()) {
startReadyPulse();
return;
}
const deadline = Date.now() + 60_000;
const timer = window.setInterval(() => {
if (isPluginApiReady()) {
window.clearInterval(timer);
startReadyPulse();
return;
}
if (Date.now() > deadline) {
window.clearInterval(timer);
safePostToTop({ type: "result", callId: "bridge_bootstrap", ok: false, error: "ONLYOFFICE 插件 API 长时间未就绪" });
}
}, 500);
};
const execMethod = (method, args) =>
new Promise((resolve, reject) => {
try {
@@ -74,15 +120,19 @@
window.Asc.plugin = window.Asc.plugin || {};
window.Asc.plugin.init = function () {
safePostToTop({ type: "ready" });
startReadyPulse();
};
waitForPluginApiReady();
window.addEventListener("message", async (ev) => {
const msg = ev && ev.data ? ev.data : null;
if (!msg || typeof msg !== "object") return;
if (msg.channel !== CHANNEL) return;
if (msg.type !== "call") return;
stopReadyPulse();
const callId = String(msg.callId ?? "").trim();
const tool = String(msg.tool ?? "").trim();
const args = msg.args && typeof msg.args === "object" ? msg.args : {};
@@ -97,4 +147,3 @@
}
});
})();