fix(wechat): complement page link delivery when reply references public html
Memind CI / Test, build, and release guards (push) Failing after 7s
Memind CI / Test, build, and release guards (push) Failing after 7s
Intent routing and reply content now both trigger HTML delivery: public links, public/*.html paths, or html writes in the agent reply enable artifact recovery, link attachment, and fail-closed when the claimed page is missing. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+97
-13
@@ -565,6 +565,38 @@ function hasAnyPublicHtmlLink(text) {
|
||||
return [...String(text ?? '').matchAll(PUBLIC_HTML_LINK_PATTERN)].length > 0;
|
||||
}
|
||||
|
||||
const PUBLIC_HTML_PATH_REFERENCE_PATTERN =
|
||||
/(?:^|[\s`'"])(public\/[a-z0-9._-]+\.html)\b/i;
|
||||
|
||||
function hasPublicHtmlPathReference(text) {
|
||||
return PUBLIC_HTML_PATH_REFERENCE_PATTERN.test(String(text ?? ''));
|
||||
}
|
||||
|
||||
export function hasAnyPublicHtmlLinkInReply(reply) {
|
||||
return collectWechatAgentReplyVisibleTexts(reply).some((text) => hasAnyPublicHtmlLink(text));
|
||||
}
|
||||
|
||||
function hasPublicHtmlPathReferenceInReply(reply) {
|
||||
return collectWechatAgentReplyVisibleTexts(reply).some((text) => hasPublicHtmlPathReference(text));
|
||||
}
|
||||
|
||||
export function replyImpliesPublicHtmlDelivery(reply) {
|
||||
if (hasAnyPublicHtmlLinkInReply(reply)) return true;
|
||||
if (hasPublicHtmlPathReferenceInReply(reply)) return true;
|
||||
return extractHtmlWriteTargets(replyRequestMessages(reply)).length > 0;
|
||||
}
|
||||
|
||||
export function shouldFailClosedOnMissingPublicHtmlDelivery({
|
||||
reply,
|
||||
confirmedArtifacts = [],
|
||||
hasValidLinkInReply = false,
|
||||
} = {}) {
|
||||
if (!replyImpliesPublicHtmlDelivery(reply)) return false;
|
||||
if (nonStubHtmlArtifacts(confirmedArtifacts).length > 0) return false;
|
||||
if (hasValidLinkInReply) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function collectPublicHtmlLinkFilenames(text) {
|
||||
const filenames = new Set();
|
||||
for (const match of String(text ?? '').matchAll(PUBLIC_HTML_LINK_PATTERN)) {
|
||||
@@ -857,10 +889,7 @@ async function resolveHtmlPublishArtifacts({
|
||||
intent?.agentText,
|
||||
) ||
|
||||
isWechatPageDataTask(intent?.agentText) ||
|
||||
hasAnyPublicHtmlLink(reply?.text) ||
|
||||
extractHtmlWriteTargets(
|
||||
replyRequestMessages(reply),
|
||||
).length > 0;
|
||||
replyImpliesPublicHtmlDelivery(reply);
|
||||
if (
|
||||
typeof prepareDelivery !== 'function'
|
||||
) {
|
||||
@@ -961,11 +990,26 @@ export function shouldRetryHtmlGenerationReply({
|
||||
confirmedArtifacts = [],
|
||||
hasValidLinkInReply = false,
|
||||
}) {
|
||||
if (!looksLikeHtmlGenerationIntent(intent?.agentText)) return false;
|
||||
|
||||
if (nonStubHtmlArtifacts(confirmedArtifacts).length > 0) return false;
|
||||
|
||||
const replyHasPublicLinks = hasAnyPublicHtmlLink(reply?.text);
|
||||
const replyHasPublicLinks = hasAnyPublicHtmlLinkInReply(reply);
|
||||
const replyImpliesDelivery = replyImpliesPublicHtmlDelivery(reply);
|
||||
|
||||
if (replyImpliesDelivery) {
|
||||
if (replyHasPublicLinks && !hasValidLinkInReply) return true;
|
||||
if (
|
||||
extractHtmlWriteTargets(replyRequestMessages(reply)).length > 0
|
||||
&& confirmedArtifacts.length === 0
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
if (hasPublicHtmlPathReferenceInReply(reply) && confirmedArtifacts.length === 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!looksLikeHtmlGenerationIntent(intent?.agentText)) return false;
|
||||
|
||||
if (replyHasPublicLinks) {
|
||||
if (!hasValidLinkInReply) return true;
|
||||
if (isMissingRequiredPublishSkill(reply, intent)) return true;
|
||||
@@ -2650,6 +2694,9 @@ export function createWechatMpService({
|
||||
error.code = 'WECHAT_IMAGE_GENERATION_REQUIRED';
|
||||
throw error;
|
||||
}
|
||||
const replyImpliesHtmlDelivery = replyImpliesPublicHtmlDelivery(reply);
|
||||
const effectiveHtmlDelivery = htmlArtifactDeliveryExpected || replyImpliesHtmlDelivery;
|
||||
const allowRecentForDelivery = allowHtmlArtifactRecovery || replyImpliesHtmlDelivery;
|
||||
const {
|
||||
publishedArtifacts,
|
||||
expectedArtifacts,
|
||||
@@ -2665,7 +2712,7 @@ export function createWechatMpService({
|
||||
userId: user.userId,
|
||||
sessionId,
|
||||
onPageGenerated,
|
||||
allowRecentArtifacts: allowHtmlArtifactRecovery,
|
||||
allowRecentArtifacts: allowRecentForDelivery,
|
||||
htmlDeliveryAuthority,
|
||||
});
|
||||
confirmedArtifacts = resolvedConfirmedArtifacts;
|
||||
@@ -2686,7 +2733,7 @@ export function createWechatMpService({
|
||||
linkExistsForRequest,
|
||||
{ confirmedArtifacts },
|
||||
);
|
||||
const replyHasPublicLinks = hasAnyPublicHtmlLink(reply?.text);
|
||||
const replyHasPublicLinks = hasAnyPublicHtmlLinkInReply(reply);
|
||||
const suspiciousPublishClaim =
|
||||
expectedArtifacts.length === 0 &&
|
||||
recentArtifacts.length === 0 &&
|
||||
@@ -2699,7 +2746,7 @@ export function createWechatMpService({
|
||||
});
|
||||
const bareCompletionReply = isSuspiciousBareCompletionReply(reply, intent);
|
||||
publishArtifacts =
|
||||
htmlArtifactDeliveryExpected || publishedArtifacts.length > 0
|
||||
effectiveHtmlDelivery || publishedArtifacts.length > 0
|
||||
? selectSendableHtmlArtifacts({ verifiedArtifacts, confirmedArtifacts })
|
||||
: [];
|
||||
|
||||
@@ -2765,6 +2812,23 @@ export function createWechatMpService({
|
||||
}
|
||||
throw markWechatUserNotified(new Error(text));
|
||||
}
|
||||
} else if (
|
||||
replyImpliesHtmlDelivery &&
|
||||
shouldFailClosedOnMissingPublicHtmlDelivery({
|
||||
reply,
|
||||
confirmedArtifacts,
|
||||
hasValidLinkInReply,
|
||||
})
|
||||
) {
|
||||
const text = buildHtmlPublishFailureText();
|
||||
try {
|
||||
await sendWechatFailureNotice(inbound.fromUserName, text, user, {
|
||||
sourceMsgId: intent.msgId,
|
||||
});
|
||||
} catch (sendErr) {
|
||||
logger.error?.('WeChat MP reply-implied html delivery failure notice failed:', sendErr);
|
||||
}
|
||||
throw markWechatUserNotified(new Error(text));
|
||||
} else if (htmlGenerationNeedsRetry || suspiciousPublishClaim) {
|
||||
throw new Error('stale_session_poisoned_completion');
|
||||
}
|
||||
@@ -2998,6 +3062,9 @@ export function createWechatMpService({
|
||||
error.code = 'WECHAT_IMAGE_GENERATION_REQUIRED';
|
||||
throw error;
|
||||
}
|
||||
const replyImpliesHtmlDelivery = replyImpliesPublicHtmlDelivery(reply);
|
||||
const effectiveHtmlDelivery = htmlArtifactDeliveryExpected || replyImpliesHtmlDelivery;
|
||||
const allowRecentForDelivery = allowHtmlArtifactRecovery || replyImpliesHtmlDelivery;
|
||||
const {
|
||||
publishedArtifacts,
|
||||
verifiedArtifacts,
|
||||
@@ -3013,7 +3080,7 @@ export function createWechatMpService({
|
||||
userId: user.userId,
|
||||
sessionId,
|
||||
onPageGenerated,
|
||||
allowRecentArtifacts: allowHtmlArtifactRecovery,
|
||||
allowRecentArtifacts: allowRecentForDelivery,
|
||||
htmlDeliveryAuthority,
|
||||
});
|
||||
const linkExistsForRequest =
|
||||
@@ -3032,7 +3099,7 @@ export function createWechatMpService({
|
||||
linkExistsForRequest,
|
||||
{ confirmedArtifacts },
|
||||
);
|
||||
const replyHasPublicLinks = hasAnyPublicHtmlLink(reply?.text);
|
||||
const replyHasPublicLinks = hasAnyPublicHtmlLinkInReply(reply);
|
||||
const suspiciousPublishClaim =
|
||||
expectedArtifacts.length === 0 &&
|
||||
recentArtifacts.length === 0 &&
|
||||
@@ -3045,7 +3112,7 @@ export function createWechatMpService({
|
||||
});
|
||||
const bareCompletionReply = isSuspiciousBareCompletionReply(reply, intent);
|
||||
let publishArtifacts =
|
||||
htmlArtifactDeliveryExpected || publishedArtifacts.length > 0
|
||||
effectiveHtmlDelivery || publishedArtifacts.length > 0
|
||||
? selectSendableHtmlArtifacts({ verifiedArtifacts, confirmedArtifacts })
|
||||
: [];
|
||||
|
||||
@@ -3094,6 +3161,23 @@ export function createWechatMpService({
|
||||
}
|
||||
throw markWechatUserNotified(new Error(text));
|
||||
}
|
||||
} else if (
|
||||
replyImpliesHtmlDelivery &&
|
||||
shouldFailClosedOnMissingPublicHtmlDelivery({
|
||||
reply,
|
||||
confirmedArtifacts,
|
||||
hasValidLinkInReply,
|
||||
})
|
||||
) {
|
||||
const text = buildHtmlPublishFailureText();
|
||||
try {
|
||||
await sendWechatFailureNotice(inbound.fromUserName, text, user, {
|
||||
sourceMsgId: intent.msgId,
|
||||
});
|
||||
} catch (sendErr) {
|
||||
logger.error?.('WeChat MP reply-implied html delivery retry failure notice failed:', sendErr);
|
||||
}
|
||||
throw markWechatUserNotified(new Error(text));
|
||||
} else if (htmlGenerationNeedsRetry || suspiciousPublishClaim) {
|
||||
throw new Error(buildHtmlPublishFailureText());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user