feat(wechat): add image generation delivery policy
Memind CI / Test, build, and release guards (pull_request) Successful in 2m45s

This commit is contained in:
john
2026-07-21 23:21:44 +08:00
parent bfb1f6fea9
commit 28581310da
13 changed files with 1078 additions and 19 deletions
+7 -1
View File
@@ -2,8 +2,9 @@ import { buildAutoChatSkillPrefix, isPageDataIntent } from '../../chat-skills.mj
import { shouldUseScheduleAssistant } from '../../schedule-intent.mjs';
import { buildCurrentTimeAgentPrefix } from '../../user-memory-profile.mjs';
import { isPageGenerateText, wantsDocxDownload } from '../intent/patterns.mjs';
import { buildWechatStandaloneImageInstruction } from '../image-generation-policy.mjs';
export function buildWechatAgentPrompt(intent, { grantedSkills = [] } = {}) {
export function buildWechatAgentPrompt(intent, { grantedSkills = [], imagePolicy = null } = {}) {
const msgType = String(intent?.msgType ?? 'text');
const agentText = intent?.agentText ?? intent?.content ?? '';
const autoSkillPrefix =
@@ -54,6 +55,9 @@ export function buildWechatAgentPrompt(intent, { grantedSkills = [] } = {}) {
'',
].filter(Boolean).join('\n')
: '';
const imageGenerationHint = buildWechatStandaloneImageInstruction(imagePolicy, {
sourceMessageId: intent?.msgId,
});
if (msgType === 'voice') {
return [
@@ -61,6 +65,7 @@ export function buildWechatAgentPrompt(intent, { grantedSkills = [] } = {}) {
pageDataCollectHint,
currentTimeHint,
scheduleAssistantHint,
imageGenerationHint,
'【微信服务号语音消息】用户通过语音输入,以下是微信识别结果。',
'',
`用户语音识别文本:${autoSkillPrefix}${String(agentText).trim()}`,
@@ -132,6 +137,7 @@ export function buildWechatAgentPrompt(intent, { grantedSkills = [] } = {}) {
if (pageDataCollectHint) lines.push(pageDataCollectHint);
if (pagePublishHint) lines.push(pagePublishHint);
if (scheduleAssistantHint) lines.push(scheduleAssistantHint);
if (imageGenerationHint) lines.push(imageGenerationHint);
lines.push(
'【微信服务号新消息】请只回答下面这条用户消息,不要主动延续无关的历史话题。',
'若用户只是在测试连通性,请一句话确认收到即可,不要展开旧任务。',
+26 -6
View File
@@ -1,9 +1,10 @@
import { buildCurrentTimeAgentPrefix } from '../../user-memory-profile.mjs';
import { buildWechatPageImageInstruction } from '../image-generation-policy.mjs';
/**
* Service-account-only page generation prompt. Does not use H5 buildAutoChatSkillPrefix.
*/
export function buildPageGenerateAgentPrompt(intent, { wantsDocx = false } = {}) {
export function buildPageGenerateAgentPrompt(intent, { wantsDocx = false, imagePolicy = null } = {}) {
const topic = String(intent?.agentText ?? intent?.displayText ?? '').trim();
const scheduleTimezone = process.env.H5_DEFAULT_TIMEZONE || 'Asia/Shanghai';
const docxBlock = wantsDocx
@@ -13,24 +14,33 @@ export function buildPageGenerateAgentPrompt(intent, { wantsDocx = false } = {})
'',
].join('\n')
: '';
const imageBlock = buildWechatPageImageInstruction(imagePolicy, {
sourceMessageId: intent?.msgId,
});
const coverExample = imageBlock
? '<本轮 generate_image 返回的 asset.htmlSrc>'
: 'assets/hero.jpg';
return [
'【微信服务号 · 页面生成任务】',
'这是服务号专用页面生成,不是普通聊天。必须按步骤完成,未完成前禁止告诉用户“已生成/已发布”。',
'',
docxBlock,
imageBlock,
'步骤(必须全部完成):',
'1. 调用 `load_skill`,参数 name=`static-page-publish`。',
'1. 必须先调用 `load_skill`,参数 name=`static-page-publish`。',
'2. 阅读技能说明后,用 sandbox-fs 的 `write_file` 或 `edit_file` 写入 `public/*.html`。',
'3. 禁止 shell/cat/heredoc/cp 写 HTML(不会出现在公网 MindSpace)。',
'4. 写完后确认目标文件已落盘,且内容是用户要的完整页面(不是占位 stub)。',
'5. 在 `<head>` 写入微信分享卡片所需元数据(必须):',
' - `<meta name="description" content="一句话摘要">`',
' - `<meta name="mindspace-cover" content=\'{"tag":"主题","accent":"#主色","accent2":"#辅色","subtitle":"卖点","cover":"assets/hero.jpg"}\'>`',
' tag/accent/subtitle 必须与页面主题一致;有 hero 图时 cover 指向同目录 raster 图(jpg/png)。',
` - \`<meta name="mindspace-cover" content='{"tag":"主题","accent":"#主色","accent2":"#辅色","subtitle":"卖点","cover":"${coverExample}"}'>\``,
imageBlock
? ' tag/accent/subtitle 必须与页面主题一致;cover 必须引用本轮新生成资产,不得省略、复用旧图或填写占位路径。'
: ' tag/accent/subtitle 必须与页面主题一致;有 hero 图时 cover 指向同目录 raster 图(jpg/png)。',
'6. 交付前运行 `npm run check:mindspace-cover`(或 node scripts/check-mindspace-cover.mjs --user <uid>);有 error 则补元数据后再回复链接。',
'7. 页脚加 `<p data-mindspace-page-tag="platform-brand">TKMind · 智趣</p>`(必须;禁止省略、不要用邮箱/tkmind.ai,也不要把该行 opacity 设太低导致看不见)。',
'8. 回复里只给一个正式域名链接;没有落盘或缺少上述元数据就不要发链接。',
'8. 回复里只给一个正式域名的唯一正确链接;没有落盘或缺少上述元数据就不要发链接。',
'',
buildCurrentTimeAgentPrefix({ timezone: scheduleTimezone }),
`用户需求:${topic}`,
@@ -39,7 +49,17 @@ export function buildPageGenerateAgentPrompt(intent, { wantsDocx = false } = {})
.join('\n');
}
export function buildPagePublishFailureText({ missingSharePreview = false, missingPlatformBrand = false } = {}) {
export function buildPagePublishFailureText({
missingSharePreview = false,
missingPlatformBrand = false,
missingFreshThumbnail = false,
} = {}) {
if (missingFreshThumbnail) {
return [
'这次页面内容已生成,但没有完成服务号要求的本轮新缩略图,所以我先不发页面链接。',
'请直接重发一次完整页面需求,我会重新生成主题匹配的新缩略图并完成页面交付。',
].join('\n');
}
if (missingPlatformBrand) {
return [
'这次页面已落盘,但缺少页脚平台品牌标记(data-mindspace-page-tag="platform-brand"),所以我先不发链接。',