fix: guard WeChat Page Data delivery with Aider review
Memind CI / Test, build, and release guards (push) Has been cancelled
Memind CI / Test, build, and release guards (push) Has been cancelled
This commit is contained in:
+81
-4
@@ -27,7 +27,10 @@ import {
|
||||
resolveWechatSessionAction,
|
||||
} from './wechat/intent/session-action.mjs';
|
||||
import { isPageGenerateText, isTopicResetText } from './wechat/intent/patterns.mjs';
|
||||
import { isPageDataIntent } from './chat-skills.mjs';
|
||||
import {
|
||||
isPageDataDevIntent,
|
||||
isPageDataIntent,
|
||||
} from './chat-skills.mjs';
|
||||
import { resolvePageGenerateOutcome } from './wechat/handlers/page-generate.mjs';
|
||||
import {
|
||||
buildWechatImageRunMetadata,
|
||||
@@ -833,7 +836,7 @@ async function resolveHtmlPublishArtifacts({
|
||||
looksLikeHtmlGenerationIntent(
|
||||
intent?.agentText,
|
||||
) ||
|
||||
isPageDataIntent(intent?.agentText) ||
|
||||
isWechatPageDataTask(intent?.agentText) ||
|
||||
hasAnyPublicHtmlLink(reply?.text) ||
|
||||
extractHtmlWriteTargets(
|
||||
replyRequestMessages(reply),
|
||||
@@ -970,6 +973,10 @@ export function shouldForceNewWechatAgentSession(wechatIntent, resetCandidate) {
|
||||
);
|
||||
}
|
||||
|
||||
export function isWechatPageDataTask(text) {
|
||||
return isPageDataIntent(text) || isPageDataDevIntent(text);
|
||||
}
|
||||
|
||||
export function isRecoverableWechatAgentSessionError(message) {
|
||||
const normalized = String(message ?? '').trim();
|
||||
if (!normalized) return false;
|
||||
@@ -1457,6 +1464,7 @@ export function createWechatMpService({
|
||||
sessionIntentClassifier = null,
|
||||
htmlDeliveryAuthority = null,
|
||||
pageDataFinishGuard = null,
|
||||
pageDataDeliveryReviewer = null,
|
||||
wechatFetch = undiciFetch,
|
||||
linkExists = defaultPublicHtmlLinkExists,
|
||||
logger = console,
|
||||
@@ -1489,6 +1497,12 @@ export function createWechatMpService({
|
||||
reliabilityGrayUsers: Array.isArray(config.reliabilityGrayUsers)
|
||||
? config.reliabilityGrayUsers
|
||||
: [],
|
||||
pageDataAiderReviewEnabled:
|
||||
config.pageDataAiderReviewEnabled === true,
|
||||
pageDataAiderReviewUsers:
|
||||
Array.isArray(config.pageDataAiderReviewUsers)
|
||||
? config.pageDataAiderReviewUsers
|
||||
: [],
|
||||
agentReplyTimeoutMs: Math.max(
|
||||
0,
|
||||
Number(config.agentReplyTimeoutMs ?? DEFAULT_WECHAT_AGENT_REPLY_TIMEOUT_MS),
|
||||
@@ -2268,6 +2282,46 @@ export function createWechatMpService({
|
||||
}
|
||||
};
|
||||
|
||||
const reviewWechatPageDataArtifacts = async ({
|
||||
user,
|
||||
requestId,
|
||||
sessionId,
|
||||
sourceMessageId,
|
||||
originalUserText,
|
||||
requestStartedAt,
|
||||
artifacts,
|
||||
forcePageData,
|
||||
}) => {
|
||||
const enabledForUser =
|
||||
config.pageDataAiderReviewEnabled &&
|
||||
isWechatMediaGrayUser(user, config.pageDataAiderReviewUsers);
|
||||
if (!enabledForUser) return { action: 'skip', reason: 'disabled' };
|
||||
if (typeof pageDataDeliveryReviewer?.reviewIfNeeded !== 'function') {
|
||||
const error = new Error('微信 Page Data 强制 Aider 审核服务不可用');
|
||||
error.code = 'PAGE_DATA_REVIEW_UNAVAILABLE';
|
||||
error.retryable = false;
|
||||
throw error;
|
||||
}
|
||||
const relativePaths = [
|
||||
...new Set(
|
||||
(Array.isArray(artifacts) ? artifacts : [])
|
||||
.map((artifact) => String(artifact?.relativePath ?? '').trim())
|
||||
.filter(Boolean),
|
||||
),
|
||||
];
|
||||
return pageDataDeliveryReviewer.reviewIfNeeded({
|
||||
sourceChannel: 'wechat_mp',
|
||||
userId: user.userId,
|
||||
requestId,
|
||||
sessionId,
|
||||
sourceMessageId,
|
||||
originalUserText,
|
||||
relativePaths,
|
||||
requestStartedAt,
|
||||
forcePageData,
|
||||
});
|
||||
};
|
||||
|
||||
const runIntentMessage = async ({ inbound, intent, user }) => {
|
||||
const wechatIntent = await resolveWechatIntent(intent);
|
||||
const mediaAnalysisEnabled = isWechatMediaGrayUser(user, config.mediaAnalysisGrayUsers);
|
||||
@@ -2283,7 +2337,7 @@ export function createWechatMpService({
|
||||
// Page Data delivery owns persistent files, datasets and two publication
|
||||
// policies. Reusing a conversational route here can make a new request
|
||||
// inspect/retry unrelated historical pages from that session.
|
||||
const isPageDataRequest = isPageDataIntent(resetCandidate);
|
||||
const isPageDataRequest = isWechatPageDataTask(resetCandidate);
|
||||
const htmlArtifactDeliveryExpected = shouldDeliverWechatHtmlArtifacts(wechatIntent, intent);
|
||||
const forceNew = shouldForceNewWechatAgentSession(wechatIntent, resetCandidate);
|
||||
let route = await ensureWechatAgentSession({
|
||||
@@ -2450,6 +2504,16 @@ export function createWechatMpService({
|
||||
} else if (htmlGenerationNeedsRetry || suspiciousPublishClaim) {
|
||||
throw new Error('stale_session_poisoned_completion');
|
||||
}
|
||||
await reviewWechatPageDataArtifacts({
|
||||
user,
|
||||
requestId,
|
||||
sessionId,
|
||||
sourceMessageId: intent.msgId,
|
||||
originalUserText: resetCandidate,
|
||||
requestStartedAt,
|
||||
artifacts: [...confirmedArtifacts, ...publishArtifacts],
|
||||
forcePageData: isPageDataRequest,
|
||||
});
|
||||
if (wechatIntent.kind === 'page.generate') {
|
||||
await enforceFreshPageThumbnailDelivery({
|
||||
artifacts: publishArtifacts,
|
||||
@@ -2520,7 +2584,10 @@ export function createWechatMpService({
|
||||
// another session while the finish guard is also active can turn one
|
||||
// request into repairs against historical pages. Drop only this user's
|
||||
// route so the next explicit request starts cleanly.
|
||||
if (isPageDataRequest) {
|
||||
if (
|
||||
isPageDataRequest ||
|
||||
String(err?.code ?? '').startsWith('PAGE_DATA_REVIEW_')
|
||||
) {
|
||||
await userAuth.clearWechatAgentRoute(config.appId, inbound.fromUserName).catch((clearErr) => {
|
||||
logger.warn?.('WeChat MP page data route clear failed:', clearErr);
|
||||
});
|
||||
@@ -2678,6 +2745,16 @@ export function createWechatMpService({
|
||||
} else if (htmlGenerationNeedsRetry || suspiciousPublishClaim) {
|
||||
throw new Error(buildHtmlPublishFailureText());
|
||||
}
|
||||
await reviewWechatPageDataArtifacts({
|
||||
user,
|
||||
requestId: retryId,
|
||||
sessionId,
|
||||
sourceMessageId: intent.msgId,
|
||||
originalUserText: resetCandidate,
|
||||
requestStartedAt: retryStartedAt,
|
||||
artifacts: [...confirmedArtifacts, ...publishArtifacts],
|
||||
forcePageData: isPageDataRequest,
|
||||
});
|
||||
if (wechatIntent.kind === 'page.generate') {
|
||||
await enforceFreshPageThumbnailDelivery({
|
||||
artifacts: publishArtifacts,
|
||||
|
||||
Reference in New Issue
Block a user