From 31fb0e02cfe9905a809a911a4fd66ce6adfef70a Mon Sep 17 00:00:00 2001 From: john Date: Sat, 4 Jul 2026 14:00:26 +0800 Subject: [PATCH] feat(wechat): require share preview meta before page link delivery Block service-account page links when HTML lacks mindspace-cover and description so WeChat forwards always get TKMind branding and thumbnail. Co-authored-by: Cursor --- wechat/handlers/page-generate.mjs | 15 +++++++- wechat/prompts/page-generate.mjs | 15 +++++++- wechat/verify/share-preview.mjs | 64 +++++++++++++++++++++++++++++++ wechat/wechat-channel.test.mjs | 55 ++++++++++++++++++++++++++ 4 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 wechat/verify/share-preview.mjs diff --git a/wechat/handlers/page-generate.mjs b/wechat/handlers/page-generate.mjs index e22eb7b..2192077 100644 --- a/wechat/handlers/page-generate.mjs +++ b/wechat/handlers/page-generate.mjs @@ -1,10 +1,12 @@ import { buildPagePublishFailureText } from '../prompts/page-generate.mjs'; import { selectSendableHtmlArtifacts, verifyPageArtifactContent } from '../verify/page-artifact.mjs'; +import { filterSharePreviewReadyArtifacts } from '../verify/share-preview.mjs'; export function evaluatePageGenerateSendableArtifacts({ verifiedArtifacts = [], confirmedArtifacts = [] } = {}) { const sendable = selectSendableHtmlArtifacts({ verifiedArtifacts, confirmedArtifacts }); const verified = sendable.filter((artifact) => verifyPageArtifactContent(artifact).ok); - return verified.length > 0 ? verified : sendable; + const candidates = verified.length > 0 ? verified : sendable; + return filterSharePreviewReadyArtifacts(candidates); } /** @@ -42,6 +44,17 @@ export function resolvePageGenerateOutcome({ }; } + const previewCandidates = filterSharePreviewReadyArtifacts( + selectSendableHtmlArtifacts({ verifiedArtifacts, confirmedArtifacts }), + ); + if (previewCandidates.length === 0 && confirmedArtifacts.length > 0) { + return { + action: 'fail', + failureText: buildPagePublishFailureText({ missingSharePreview: true }), + reason: 'missing_share_preview', + }; + } + if (!String(reply?.text ?? '').trim() && sendable.length === 0) { return { action: 'fail', diff --git a/wechat/prompts/page-generate.mjs b/wechat/prompts/page-generate.mjs index 64c0aae..684f0eb 100644 --- a/wechat/prompts/page-generate.mjs +++ b/wechat/prompts/page-generate.mjs @@ -24,7 +24,12 @@ export function buildPageGenerateAgentPrompt(intent, { wantsDocx = false } = {}) '2. 阅读技能说明后,用 sandbox-fs 的 `write_file` 或 `edit_file` 写入 `public/*.html`。', '3. 禁止 shell/cat/heredoc/cp 写 HTML(不会出现在公网 MindSpace)。', '4. 写完后确认目标文件已落盘,且内容是用户要的完整页面(不是占位 stub)。', - '5. 回复里只给一个正式域名链接;没有落盘就不要发链接。', + '5. 在 `` 写入微信分享卡片所需元数据(必须):', + ' - ``', + ' - ``', + ' tag/accent/subtitle 必须与页面主题一致;有 hero 图时 cover 指向同目录 raster 图(jpg/png)。', + '6. 页脚加 `