fix: fail closed when WeChat page.generate has no HTML artifact
Prevent text-only planning replies from marking WeChat delivery done when static-page-publish never confirmed a public HTML file. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+6
-5
@@ -3288,8 +3288,8 @@ test('wechat mp service forwards H5 agent text when page generation produced no
|
||||
assert.equal(fs.existsSync(htmlPath), false);
|
||||
const sendCall = wechatCalls.find(([url]) => String(url).includes('/cgi-bin/message/custom/send'));
|
||||
const payload = JSON.parse(sendCall[2]);
|
||||
assert.match(payload.text.content, /🌴 泰国简易攻略/);
|
||||
assert.doesNotMatch(payload.text.content, /没有按 H5 里的页面技能真正生成成功/);
|
||||
assert.doesNotMatch(payload.text.content, /🌴 泰国简易攻略/);
|
||||
assert.match(payload.text.content, /没有按服务号页面技能真正生成成功/);
|
||||
assert.doesNotMatch(payload.text.content, /https:\/\/m\.tkmind\.cn\/MindSpace\/.+\/public\/thailand-guide\.html/);
|
||||
});
|
||||
|
||||
@@ -3631,7 +3631,8 @@ test('wechat mp service recreates dedicated session when tool_calls error arrive
|
||||
assert.equal(started, true);
|
||||
const sendCall = wechatCalls.find(([url]) => String(url).includes('/cgi-bin/message/custom/send'));
|
||||
const payload = JSON.parse(sendCall[2]);
|
||||
assert.match(payload.text.content, /已恢复,可以继续对话/);
|
||||
assert.doesNotMatch(payload.text.content, /已恢复,可以继续对话/);
|
||||
assert.match(payload.text.content, /没有按服务号页面技能真正生成成功/);
|
||||
assert.doesNotMatch(payload.text.content, /Bad request/);
|
||||
assert.doesNotMatch(payload.text.content, /tool_calls/);
|
||||
});
|
||||
@@ -3965,8 +3966,8 @@ test('wechat mp service retries poisoned publish claims before forwarding H5 ret
|
||||
const sendCall = wechatCalls.find(([url]) => String(url).includes('/cgi-bin/message/custom/send'));
|
||||
const payload = JSON.parse(sendCall[2]);
|
||||
assert.doesNotMatch(payload.text.content, /页面都已经成功发布了|主题页面已发布/);
|
||||
assert.match(payload.text.content, /🌴 夏日主题页面/);
|
||||
assert.doesNotMatch(payload.text.content, /没有按 H5 里的页面技能真正生成成功/);
|
||||
assert.doesNotMatch(payload.text.content, /🌴 夏日主题页面/);
|
||||
assert.match(payload.text.content, /没有按服务号页面技能真正生成成功/);
|
||||
assert.doesNotMatch(payload.text.content, /summer-breeze-journal\.html/);
|
||||
});
|
||||
|
||||
|
||||
@@ -69,5 +69,11 @@ export function resolvePageGenerateOutcome({
|
||||
};
|
||||
}
|
||||
|
||||
return { action: 'send', artifacts: sendable };
|
||||
// Fail closed: page.generate must deliver a verified public HTML artifact.
|
||||
// Text-only planning replies ("我先搜索…") must not mark WeChat delivery done.
|
||||
return {
|
||||
action: 'fail',
|
||||
failureText: buildPagePublishFailureText(),
|
||||
reason: 'missing_page_artifact',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -218,3 +218,29 @@ test('resolvePageGenerateOutcome sends when share preview meta is present', () =
|
||||
assert.equal(outcome.action, 'send');
|
||||
assert.equal(outcome.artifacts.length, 1);
|
||||
});
|
||||
|
||||
test('resolvePageGenerateOutcome fails closed on planning text without html artifact', () => {
|
||||
const outcome = resolvePageGenerateOutcome({
|
||||
reply: {
|
||||
text: '找到了之前的新闻页面。让我先读取最新的页面格式作为参考,同时并行搜索今日新闻和天气。',
|
||||
},
|
||||
confirmedArtifacts: [],
|
||||
verifiedArtifacts: [],
|
||||
});
|
||||
assert.equal(outcome.action, 'fail');
|
||||
assert.equal(outcome.reason, 'missing_page_artifact');
|
||||
assert.match(outcome.failureText, /没有按服务号页面技能真正生成成功|static-page-publish/);
|
||||
});
|
||||
|
||||
test('resolvePageGenerateOutcome fails closed when reply links an old page but no artifact confirmed', () => {
|
||||
const outcome = resolvePageGenerateOutcome({
|
||||
reply: {
|
||||
text: '[每日新闻](https://m.tkmind.cn/MindSpace/u/public/daily-news-0728.html)',
|
||||
},
|
||||
confirmedArtifacts: [],
|
||||
verifiedArtifacts: [],
|
||||
replyHasPublicLinks: true,
|
||||
});
|
||||
assert.equal(outcome.action, 'fail');
|
||||
assert.equal(outcome.reason, 'missing_page_artifact');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user