|
|
@@ -52,6 +52,9 @@ const stubFetchWith = (sseText) => {
|
|
|
};
|
|
|
};
|
|
|
|
|
|
+/** 把一轮里收集到的 message 事件拼成整条内容 */
|
|
|
+const seen_message_text = (seen) => (seen.messages || []).join('\n\n');
|
|
|
+
|
|
|
const runTurn = async (events) => {
|
|
|
stubFetchWith(sse(events));
|
|
|
const coordinator = new ApiChatCoordinator({ baseUrl: 'http://stub', threadId: 't1' });
|
|
|
@@ -149,5 +152,69 @@ console.log('\n【4】跨轮不串:上一轮有 company_info,下一轮没有
|
|
|
check('第二轮**没有**沿用上一轮的 company_info(resetTurnContent 生效)', !('company_info' in (payloads[1] || {})), payloads[1]);
|
|
|
}
|
|
|
|
|
|
+console.log('\n【5】result.cipa → 企业微信二维码块(<image-scope>)');
|
|
|
+{
|
|
|
+ const shown = await runTurn([
|
|
|
+ ...BASE_EVENTS,
|
|
|
+ ['result', { response: '这是回答正文。', cipa: true }],
|
|
|
+ ['done', { status: 'completed' }],
|
|
|
+ ]);
|
|
|
+ const text = seen_message_text(shown);
|
|
|
+ check('cipa=true → 追加 <image-scope> 块', /<image-scope>[\s\S]*?<\/image-scope>/.test(text), text.slice(-120));
|
|
|
+ check('块里有非空的图片地址', /<image-scope>\s*\S[^\n]*\s*<\/image-scope>/.test(text));
|
|
|
+ check('图片块在整条内容的**最末尾**(正文之后)', text.trimEnd().endsWith('</image-scope>'));
|
|
|
+ check('正文本身没被污染(正文仍在最前面)', text.trimStart().startsWith('这是回答正文。'), text.slice(0, 40));
|
|
|
+
|
|
|
+ const off = await runTurn([
|
|
|
+ ...BASE_EVENTS,
|
|
|
+ ['result', { response: '这是回答正文。', cipa: false }],
|
|
|
+ ['done', { status: 'completed' }],
|
|
|
+ ]);
|
|
|
+ check('cipa=false → 不加图片块', !seen_message_text(off).includes('image-scope'));
|
|
|
+
|
|
|
+ const missing = await runTurn([
|
|
|
+ ...BASE_EVENTS,
|
|
|
+ ['result', { response: '这是回答正文。' }],
|
|
|
+ ['done', { status: 'completed' }],
|
|
|
+ ]);
|
|
|
+ check('result 里没有 cipa 字段 → 不加图片块', !seen_message_text(missing).includes('image-scope'));
|
|
|
+
|
|
|
+ const truthyString = await runTurn([
|
|
|
+ ...BASE_EVENTS,
|
|
|
+ ['result', { response: 'x', cipa: 'true' }],
|
|
|
+ ['done', { status: 'completed' }],
|
|
|
+ ]);
|
|
|
+ check('非布尔值一律当 false(严格 === true)', !seen_message_text(truthyString).includes('image-scope'));
|
|
|
+}
|
|
|
+
|
|
|
+console.log('\n【6】cipa 跨轮不串(resetTurnContent 生效)');
|
|
|
+{
|
|
|
+ stubFetchWith(
|
|
|
+ sse([
|
|
|
+ ...BASE_EVENTS,
|
|
|
+ ['result', { response: '第一轮', cipa: true }],
|
|
|
+ ['done', { status: 'completed' }],
|
|
|
+ ])
|
|
|
+ );
|
|
|
+ const coordinator = new ApiChatCoordinator({ baseUrl: 'http://stub', threadId: 't1' });
|
|
|
+ const rounds = [];
|
|
|
+ coordinator.addEventListener('message', (msg) => rounds.push(msg));
|
|
|
+ await coordinator.generateAnswer('第一轮');
|
|
|
+ await new Promise((resolve) => setTimeout(resolve, 60));
|
|
|
+
|
|
|
+ stubFetchWith(
|
|
|
+ sse([
|
|
|
+ ...BASE_EVENTS,
|
|
|
+ ['result', { response: '第二轮' }], // 这一轮 cipa 缺省
|
|
|
+ ['done', { status: 'completed' }],
|
|
|
+ ])
|
|
|
+ );
|
|
|
+ await coordinator.generateAnswer('第二轮');
|
|
|
+ await new Promise((resolve) => setTimeout(resolve, 60));
|
|
|
+
|
|
|
+ check('第一轮有图片块', /<image-scope>/.test(rounds[0] || ''));
|
|
|
+ check('第二轮**没有**沿用上一轮的 cipa', !/<image-scope>/.test(rounds[1] || ''), (rounds[1] || '').slice(-80));
|
|
|
+}
|
|
|
+
|
|
|
console.log(`\n===== 通过 ${pass} 项,失败 ${fail} 项 =====`);
|
|
|
process.exit(fail ? 1 : 0);
|