fix(canvas): 助手会话 - 剥离工具执行结果中的画布快照,防止工程数据超4MB导致同步死锁 (#412)
1. 在 canvas-assistant-panel 中 executeOnlineTool 执行 ops 结果返回前,解构剔除冗余的 snapshot、before、after 全量快照对象,仅保留验证摘要及变更元数据; 2. 在 user-data-sync 的 saveRemoteUserDataBatch 同步流程中,增加 sanitizeCanvasProjectForRemoteSync,防御性清洗消息详情中可能残留的历史快照; 3. 避免大画布和多轮对话导致单个画布 JSON 膨胀突破 4MB 限制并引发未确认事务回滚死锁。
This commit is contained in:
@@ -829,7 +829,8 @@ export function CanvasAssistantPanel({
|
||||
}
|
||||
const ops = onlineToolToOps(name, args, current, effectiveConfig);
|
||||
const result = await executeOps(ops, { source: "online", conversationId: sessionId, messageId: messageId || sessionId });
|
||||
return { ok: result.ok, message: result.changed ? canvasAgentPostconditionMessage(result) : result.noopReason, data: result };
|
||||
const { snapshot: _snapshot, before: _before, after: _after, ...cleanData } = result;
|
||||
return { ok: result.ok, message: result.changed ? canvasAgentPostconditionMessage(result) : result.noopReason, data: cleanData };
|
||||
} catch (error) {
|
||||
if (isAgentSessionPollingAbort(error)) throw error;
|
||||
return { ok: false, message: error instanceof Error ? error.message : "工具执行失败" };
|
||||
|
||||
@@ -369,7 +369,7 @@ async function saveRemoteUserDataBatch(uploaded: Map<string, string>) {
|
||||
message: "正在保存画布结构",
|
||||
});
|
||||
}
|
||||
await upsertRemoteCanvasProject(remotePayload);
|
||||
await upsertRemoteCanvasProject(sanitizeCanvasProjectForRemoteSync(remotePayload));
|
||||
acknowledgedProjects.set(source.id, source);
|
||||
if (total > 0) useSyncProgressStore.getState().setProjectProgress(source.id, null);
|
||||
} catch (error) {
|
||||
@@ -513,3 +513,42 @@ function numberValue(value: unknown) {
|
||||
const number = Number(value);
|
||||
return Number.isFinite(number) && number > 0 ? number : undefined;
|
||||
}
|
||||
|
||||
function sanitizeCanvasProjectForRemoteSync<T>(project: T): T {
|
||||
if (!project || typeof project !== "object") return project;
|
||||
const clone = { ...(project as Record<string, unknown>) };
|
||||
if (Array.isArray(clone.chatSessions)) {
|
||||
clone.chatSessions = clone.chatSessions.map((session) => {
|
||||
if (!session || typeof session !== "object") return session;
|
||||
const s = { ...(session as Record<string, unknown>) };
|
||||
if (Array.isArray(s.messages)) {
|
||||
s.messages = s.messages.map((message) => {
|
||||
if (!message || typeof message !== "object" || !message.detail) return message;
|
||||
const m = { ...(message as Record<string, unknown>) };
|
||||
if (m.detail && typeof m.detail === "object") {
|
||||
const d = { ...(m.detail as Record<string, unknown>) };
|
||||
if (Array.isArray(d.results)) {
|
||||
d.results = d.results.map((r) => {
|
||||
if (!r || typeof r !== "object") return r;
|
||||
const res = { ...(r as Record<string, unknown>) };
|
||||
if (res.result && typeof res.result === "object") {
|
||||
const inner = { ...(res.result as Record<string, unknown>) };
|
||||
if (inner.data && typeof inner.data === "object") {
|
||||
const { snapshot: _s, before: _b, after: _a, ...restData } = inner.data as Record<string, unknown>;
|
||||
inner.data = restData;
|
||||
}
|
||||
res.result = inner;
|
||||
}
|
||||
return res;
|
||||
});
|
||||
}
|
||||
m.detail = d;
|
||||
}
|
||||
return m;
|
||||
});
|
||||
}
|
||||
return s;
|
||||
});
|
||||
}
|
||||
return clone as T;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user