fix(plaza): delegate thumbnail regen to chatSave authority boundary
Memind CI / Test, build, and release guards (push) Successful in 3m19s
Memind CI / Test, build, and release guards (push) Successful in 3m19s
Portal chat-share routes must not resolve workspace publish dirs directly; quick-plaza flows now call mindSpaceChatSave.ensurePreviewThumbnail instead. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+21
-21
@@ -255,8 +255,7 @@ export async function quickPlazaFromChat({
|
|||||||
mindSpacePages,
|
mindSpacePages,
|
||||||
mindSpacePublications,
|
mindSpacePublications,
|
||||||
plazaPosts,
|
plazaPosts,
|
||||||
ensureWorkspaceHtmlThumbnail,
|
mindSpaceChatSave,
|
||||||
publishDir,
|
|
||||||
}) {
|
}) {
|
||||||
if (!mindSpacePages || !mindSpacePublications || !plazaPosts) {
|
if (!mindSpacePages || !mindSpacePublications || !plazaPosts) {
|
||||||
throw Object.assign(new Error('Plaza 或 MindSpace 未启用'), { code: 'plaza_unavailable' });
|
throw Object.assign(new Error('Plaza 或 MindSpace 未启用'), { code: 'plaza_unavailable' });
|
||||||
@@ -267,29 +266,26 @@ export async function quickPlazaFromChat({
|
|||||||
userId: user.id,
|
userId: user.id,
|
||||||
bundle,
|
bundle,
|
||||||
mindSpacePages,
|
mindSpacePages,
|
||||||
ensureWorkspaceHtmlThumbnail,
|
|
||||||
publishDir,
|
|
||||||
body,
|
body,
|
||||||
skipThumbnail: !ensureWorkspaceHtmlThumbnail || !publishDir,
|
skipThumbnail: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (
|
if (
|
||||||
analysis.contentMode === 'static_html' &&
|
analysis.contentMode === 'static_html' &&
|
||||||
analysis.relativePath &&
|
analysis.relativePath &&
|
||||||
resolvedHtml?.content &&
|
resolvedHtml?.content &&
|
||||||
ensureWorkspaceHtmlThumbnail &&
|
mindSpaceChatSave?.ensurePreviewThumbnail
|
||||||
publishDir
|
|
||||||
) {
|
) {
|
||||||
await ensureWorkspaceHtmlThumbnail(
|
await mindSpaceChatSave
|
||||||
publishDir,
|
.ensurePreviewThumbnail({
|
||||||
analysis.relativePath,
|
userId: user.id,
|
||||||
resolvedHtml.content,
|
relativePath: analysis.relativePath,
|
||||||
{
|
html: resolvedHtml.content,
|
||||||
title: page.title,
|
title: page.title,
|
||||||
subtitle: page.summary,
|
subtitle: page.summary,
|
||||||
force: true,
|
force: true,
|
||||||
},
|
})
|
||||||
).catch(() => {});
|
.catch(() => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (analysis.contentMode === 'static_html' && analysis.relativePath) {
|
if (analysis.contentMode === 'static_html' && analysis.relativePath) {
|
||||||
@@ -394,8 +390,7 @@ export async function quickPlazaFromPublicHtml({
|
|||||||
mindSpacePublications,
|
mindSpacePublications,
|
||||||
plazaPosts,
|
plazaPosts,
|
||||||
readWorkspaceHtml,
|
readWorkspaceHtml,
|
||||||
ensureWorkspaceHtmlThumbnail,
|
mindSpaceChatSave,
|
||||||
publishDir,
|
|
||||||
}) {
|
}) {
|
||||||
if (!mindSpacePages || !mindSpacePublications || !plazaPosts) {
|
if (!mindSpacePages || !mindSpacePublications || !plazaPosts) {
|
||||||
throw Object.assign(new Error('Plaza 或 MindSpace 未启用'), { code: 'plaza_unavailable' });
|
throw Object.assign(new Error('Plaza 或 MindSpace 未启用'), { code: 'plaza_unavailable' });
|
||||||
@@ -421,11 +416,16 @@ export async function quickPlazaFromPublicHtml({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const title = titleFromPublicHtml(content, normalized);
|
const title = titleFromPublicHtml(content, normalized);
|
||||||
if (ensureWorkspaceHtmlThumbnail && publishDir) {
|
if (mindSpaceChatSave?.ensurePreviewThumbnail) {
|
||||||
await ensureWorkspaceHtmlThumbnail(publishDir, normalized, content, {
|
await mindSpaceChatSave
|
||||||
title,
|
.ensurePreviewThumbnail({
|
||||||
force: true,
|
userId: user.id,
|
||||||
}).catch(() => {});
|
relativePath: normalized,
|
||||||
|
html: content,
|
||||||
|
title,
|
||||||
|
force: true,
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
const page = await ensureWorkspaceHtmlPageForPlaza({
|
const page = await ensureWorkspaceHtmlPageForPlaza({
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ import {
|
|||||||
quickPlazaFromChat,
|
quickPlazaFromChat,
|
||||||
quickPlazaFromPublicHtml,
|
quickPlazaFromPublicHtml,
|
||||||
} from '../mindspace-chat-plaza.mjs';
|
} from '../mindspace-chat-plaza.mjs';
|
||||||
import { resolveMindSpaceUserPublishDir } from '../mindspace-runtime-config.mjs';
|
|
||||||
import { ensureWorkspaceHtmlThumbnail } from '../mindspace-workspace-thumbnails.mjs';
|
|
||||||
|
|
||||||
function assertRouter(api) {
|
function assertRouter(api) {
|
||||||
if (
|
if (
|
||||||
@@ -43,8 +41,6 @@ export function attachPortalMindSpaceChatShareRoutes(
|
|||||||
getQuickPlazaFromPublicHtmlStatusFn =
|
getQuickPlazaFromPublicHtmlStatusFn =
|
||||||
getQuickPlazaFromPublicHtmlStatus,
|
getQuickPlazaFromPublicHtmlStatus,
|
||||||
quickPlazaFromPublicHtmlFn = quickPlazaFromPublicHtml,
|
quickPlazaFromPublicHtmlFn = quickPlazaFromPublicHtml,
|
||||||
ensureWorkspaceHtmlThumbnailFn = ensureWorkspaceHtmlThumbnail,
|
|
||||||
resolveMindSpaceUserPublishDirFn = resolveMindSpaceUserPublishDir,
|
|
||||||
now = Date.now,
|
now = Date.now,
|
||||||
logger = console,
|
logger = console,
|
||||||
} = {},
|
} = {},
|
||||||
@@ -100,9 +96,10 @@ export function attachPortalMindSpaceChatShareRoutes(
|
|||||||
|
|
||||||
api.post('/mindspace/v1/pages/quick-plaza-from-chat', async (req, res) => {
|
api.post('/mindspace/v1/pages/quick-plaza-from-chat', async (req, res) => {
|
||||||
const pages = getMindSpacePages();
|
const pages = getMindSpacePages();
|
||||||
|
const chatSave = getMindSpaceChatSave();
|
||||||
const publications = getMindSpacePublications();
|
const publications = getMindSpacePublications();
|
||||||
const plazaPosts = getPlazaPosts();
|
const plazaPosts = getPlazaPosts();
|
||||||
if (!pages || !publications || !plazaPosts) {
|
if (!pages || !chatSave || !publications || !plazaPosts) {
|
||||||
return sendError(
|
return sendError(
|
||||||
res,
|
res,
|
||||||
req,
|
req,
|
||||||
@@ -118,7 +115,6 @@ export function attachPortalMindSpaceChatShareRoutes(
|
|||||||
h5Root,
|
h5Root,
|
||||||
req.body,
|
req.body,
|
||||||
);
|
);
|
||||||
const publishDir = resolveMindSpaceUserPublishDirFn(h5Root, req.currentUser);
|
|
||||||
const result = await quickPlazaFromChatFn({
|
const result = await quickPlazaFromChatFn({
|
||||||
user: req.currentUser,
|
user: req.currentUser,
|
||||||
bundle,
|
bundle,
|
||||||
@@ -126,8 +122,7 @@ export function attachPortalMindSpaceChatShareRoutes(
|
|||||||
mindSpacePages: pages,
|
mindSpacePages: pages,
|
||||||
mindSpacePublications: publications,
|
mindSpacePublications: publications,
|
||||||
plazaPosts,
|
plazaPosts,
|
||||||
ensureWorkspaceHtmlThumbnail: ensureWorkspaceHtmlThumbnailFn,
|
mindSpaceChatSave: chatSave,
|
||||||
publishDir,
|
|
||||||
});
|
});
|
||||||
logger.info('[quick-plaza] ok', {
|
logger.info('[quick-plaza] ok', {
|
||||||
ms: now() - startedAt,
|
ms: now() - startedAt,
|
||||||
@@ -221,7 +216,6 @@ export function attachPortalMindSpaceChatShareRoutes(
|
|||||||
req.body?.relativePath ??
|
req.body?.relativePath ??
|
||||||
'',
|
'',
|
||||||
).trim();
|
).trim();
|
||||||
const publishDir = resolveMindSpaceUserPublishDirFn(h5Root, req.currentUser);
|
|
||||||
const result = await quickPlazaFromPublicHtmlFn({
|
const result = await quickPlazaFromPublicHtmlFn({
|
||||||
user: req.currentUser,
|
user: req.currentUser,
|
||||||
relativePath,
|
relativePath,
|
||||||
@@ -230,8 +224,7 @@ export function attachPortalMindSpaceChatShareRoutes(
|
|||||||
plazaPosts,
|
plazaPosts,
|
||||||
readWorkspaceHtml: (input) =>
|
readWorkspaceHtml: (input) =>
|
||||||
chatSave.readWorkspaceHtml(input),
|
chatSave.readWorkspaceHtml(input),
|
||||||
ensureWorkspaceHtmlThumbnail: ensureWorkspaceHtmlThumbnailFn,
|
mindSpaceChatSave: chatSave,
|
||||||
publishDir,
|
|
||||||
});
|
});
|
||||||
const plazaUrl = resolvePlazaPostUrl(
|
const plazaUrl = resolvePlazaPostUrl(
|
||||||
result.post.id,
|
result.post.id,
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import assert from 'node:assert/strict';
|
import assert from 'node:assert/strict';
|
||||||
import test from 'node:test';
|
import test from 'node:test';
|
||||||
import { attachPortalMindSpaceChatShareRoutes } from './portal-mindspace-chat-share-routes.mjs';
|
import { attachPortalMindSpaceChatShareRoutes } from './portal-mindspace-chat-share-routes.mjs';
|
||||||
import { resolveMindSpaceUserPublishDir } from '../mindspace-runtime-config.mjs';
|
|
||||||
import { ensureWorkspaceHtmlThumbnail } from '../mindspace-workspace-thumbnails.mjs';
|
|
||||||
|
|
||||||
function createRouterRecorder() {
|
function createRouterRecorder() {
|
||||||
const routes = new Map();
|
const routes = new Map();
|
||||||
@@ -196,8 +194,7 @@ test('quick Plaza from chat preserves dependencies, timing, result, and errors',
|
|||||||
mindSpacePages: dependencies.services.pages,
|
mindSpacePages: dependencies.services.pages,
|
||||||
mindSpacePublications: dependencies.services.publications,
|
mindSpacePublications: dependencies.services.publications,
|
||||||
plazaPosts: dependencies.services.plazaPosts,
|
plazaPosts: dependencies.services.plazaPosts,
|
||||||
ensureWorkspaceHtmlThumbnail,
|
mindSpaceChatSave: dependencies.services.chatSave,
|
||||||
publishDir: resolveMindSpaceUserPublishDir('/workspace', req.currentUser),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const failureApi = createRouterRecorder();
|
const failureApi = createRouterRecorder();
|
||||||
|
|||||||
Reference in New Issue
Block a user