fix(wechat): rotate polluted image sessions before follow-up turns
Memind CI / Test, build, and release guards (push) Successful in 3m28s
Memind CI / Test, build, and release guards (push) Successful in 3m28s
After a successful image report flow, Goose may keep image_url parts that DeepSeek rejects on later turns while PUT scrub returns 405. Detect polluted sessions up front, rotate to a fresh agent route with carried assistant context, and recover image URLs from recent media on historical retries. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+91
-6
@@ -85,6 +85,7 @@ import { resolveMindSpaceUserPublishDir } from './mindspace-runtime-config.mjs';
|
||||
import {
|
||||
buildPageDataCollectFailureText,
|
||||
} from './mindspace-page-data-finish-guard.mjs';
|
||||
import { conversationHasImageUrlContent } from './chat-image-turn-scope.mjs';
|
||||
|
||||
export { buildWechatAgentPrompt };
|
||||
|
||||
@@ -1097,9 +1098,14 @@ export function isWechatHistoricalImageSessionError(message) {
|
||||
export const WECHAT_IMAGE_STORED_ACK_TEXT =
|
||||
'已收到图片。请直接告诉我接下来要做什么,例如:解读报告并生成页面。';
|
||||
|
||||
export function prepareWechatIntentForHistoricalImageRetry(intent) {
|
||||
export function resolveWechatRecentMediaPublicUrl(recentMediaEntry) {
|
||||
if (!recentMediaEntry?.items?.length) return '';
|
||||
return String(recentMediaEntry.items.at(-1)?.media?.publicUrl ?? '').trim();
|
||||
}
|
||||
|
||||
export function prepareWechatIntentForHistoricalImageRetry(intent, { fallbackImageUrl = '' } = {}) {
|
||||
if (!intent || typeof intent !== 'object') return intent;
|
||||
const imageUrl = String(intent.media?.publicUrl ?? '').trim();
|
||||
const imageUrl = String(intent.media?.publicUrl ?? fallbackImageUrl ?? '').trim();
|
||||
const agentText = String(intent.agentText ?? '').trim();
|
||||
if (imageUrl && !agentText.includes(imageUrl)) {
|
||||
intent.agentText = agentText
|
||||
@@ -2185,15 +2191,23 @@ export function createWechatMpService({
|
||||
retainUnlinkedRoute = false,
|
||||
userContext = null,
|
||||
}) => {
|
||||
if (forceNew) {
|
||||
await userAuth.clearWechatAgentRoute(config.appId, openid);
|
||||
}
|
||||
const workingDir = await userAuth.resolveWorkingDir(userId);
|
||||
let sessionPolicy =
|
||||
await userAuth.getAgentSessionPolicy(userId);
|
||||
const publishLayout = await userAuth.getUserPublishLayout(userId);
|
||||
const addressName = resolveWechatAddressName(userContext);
|
||||
let carriedSessionContentForNewSession = '';
|
||||
if (forceNew) {
|
||||
const routeBeforeForceNew = await userAuth.getWechatAgentRoute(config.appId, openid);
|
||||
if (routeBeforeForceNew?.agentSessionId) {
|
||||
carriedSessionContentForNewSession = await fetchLastSubstantiveAssistantFromSession(
|
||||
fetchForSession,
|
||||
routeBeforeForceNew.agentSessionId,
|
||||
);
|
||||
rememberedWechatContexts.delete(routeBeforeForceNew.agentSessionId);
|
||||
}
|
||||
await userAuth.clearWechatAgentRoute(config.appId, openid);
|
||||
}
|
||||
const existingRoute = await userAuth.getWechatAgentRoute(config.appId, openid);
|
||||
if (existingRoute?.agentSessionId) {
|
||||
const now = Date.now();
|
||||
@@ -2405,6 +2419,53 @@ export function createWechatMpService({
|
||||
};
|
||||
};
|
||||
|
||||
const rotateWechatSessionIfImagePolluted = async ({
|
||||
userId,
|
||||
openid,
|
||||
sessionId,
|
||||
user,
|
||||
carriedSessionContent = '',
|
||||
}) => {
|
||||
if (!sessionId) {
|
||||
return { sessionId, carriedSessionContent, rotated: false };
|
||||
}
|
||||
try {
|
||||
const response = await fetchForSession(
|
||||
sessionId,
|
||||
`/sessions/${encodeURIComponent(sessionId)}`,
|
||||
);
|
||||
if (!response.ok) {
|
||||
return { sessionId, carriedSessionContent, rotated: false };
|
||||
}
|
||||
const payload = await readJsonResponse(response);
|
||||
const conversation = Array.isArray(payload?.conversation) ? payload.conversation : [];
|
||||
if (!conversationHasImageUrlContent(conversation)) {
|
||||
return { sessionId, carriedSessionContent, rotated: false };
|
||||
}
|
||||
logger.warn?.('WeChat MP rotating image-polluted agent session before reply:', {
|
||||
agentSessionId: sessionId,
|
||||
conversationLength: conversation.length,
|
||||
});
|
||||
const nextRoute = await ensureWechatAgentSession({
|
||||
userId,
|
||||
openid,
|
||||
forceNew: true,
|
||||
userContext: user,
|
||||
});
|
||||
const nextCarried = String(carriedSessionContent ?? '').trim()
|
||||
|| String(nextRoute.carriedSessionContent ?? '').trim();
|
||||
return {
|
||||
sessionId: nextRoute.sessionId,
|
||||
carriedSessionContent: nextCarried,
|
||||
rotated: true,
|
||||
isNewSession: nextRoute.isNewSession,
|
||||
};
|
||||
} catch (err) {
|
||||
logger.warn?.('WeChat MP image-polluted session rotate skipped:', err);
|
||||
return { sessionId, carriedSessionContent, rotated: false };
|
||||
}
|
||||
};
|
||||
|
||||
const refreshWechatSessionSnapshot = async (sessionId, userId) => {
|
||||
if (!sessionId || !userId || typeof refreshSessionSnapshot !== 'function') return;
|
||||
try {
|
||||
@@ -2712,6 +2773,26 @@ export function createWechatMpService({
|
||||
return { sessionId };
|
||||
}
|
||||
await rememberWechatUserContext(sessionId, user, { forceBootstrap: route.isNewSession });
|
||||
const pollutionRotation = await rotateWechatSessionIfImagePolluted({
|
||||
userId: user.userId,
|
||||
openid: inbound.fromUserName,
|
||||
sessionId,
|
||||
user,
|
||||
carriedSessionContent,
|
||||
});
|
||||
if (pollutionRotation.rotated) {
|
||||
sessionId = pollutionRotation.sessionId;
|
||||
route = {
|
||||
...route,
|
||||
sessionId,
|
||||
isNewSession: pollutionRotation.isNewSession ?? true,
|
||||
};
|
||||
if (pollutionRotation.carriedSessionContent) {
|
||||
carriedSessionContent = pollutionRotation.carriedSessionContent;
|
||||
}
|
||||
await ensureSessionProvider(sessionId);
|
||||
await rememberWechatUserContext(sessionId, user, { forceBootstrap: true });
|
||||
}
|
||||
if (
|
||||
wechatIntent.kind === 'page.generate'
|
||||
&& sessionPageContinuation
|
||||
@@ -3177,7 +3258,11 @@ export function createWechatMpService({
|
||||
await ensureSessionProvider(sessionId);
|
||||
await rememberWechatUserContext(sessionId, user, { forceBootstrap: route.isNewSession });
|
||||
if (historicalImageError) {
|
||||
prepareWechatIntentForHistoricalImageRetry(intent);
|
||||
prepareWechatIntentForHistoricalImageRetry(intent, {
|
||||
fallbackImageUrl: resolveWechatRecentMediaPublicUrl(
|
||||
recentMediaByOpenid.get(String(inbound.fromUserName ?? '').trim()),
|
||||
),
|
||||
});
|
||||
}
|
||||
const retryId = crypto.randomUUID();
|
||||
const retryStartedAt = Date.now();
|
||||
|
||||
Reference in New Issue
Block a user