fix: isolate WeChat runtime delivery path

This commit is contained in:
john
2026-07-28 09:33:25 +08:00
parent 5a13950bc3
commit 7f9453433c
8 changed files with 226 additions and 9 deletions
+62 -5
View File
@@ -65,6 +65,7 @@ const DEFAULT_ASR_TARGET = process.env.H5_ASR_TARGET ?? 'https://asr.tkmind.cn';
const WECHAT_RECENT_MEDIA_TTL_MS = 15 * 60 * 1000;
const WECHAT_RECENT_IMAGE_MAX_COUNT = 10;
const DEFAULT_WECHAT_AGENT_REPLY_TIMEOUT_MS = 15 * 60 * 1000;
const WECHAT_SESSION_RESET_ACK_TEXT = '已切换到新会话,请发送你的新需求。';
export { loadWechatMpConfig };
const PUBLIC_HTML_LINK_PATTERN =
/https?:\/\/[^\s<>"')\]]+\/MindSpace\/([0-9a-f-]{36}|[a-z0-9._-]+)\/public\/([^\s<>"')\]]+\.html)/gi;
@@ -1517,6 +1518,7 @@ export function createWechatMpService({
expiresAt: 0,
};
const rememberedWechatContexts = new Map();
const confirmedWechatSessionOrigins = new Set();
const messageTasksByOpenid = new Map();
const recentMediaByOpenid = new Map();
let jsapiTicketCache = {
@@ -1527,6 +1529,19 @@ export function createWechatMpService({
const fetchForSession = (sessionId, pathname, init) =>
sessionApiFetch ? sessionApiFetch(sessionId, pathname, init) : apiFetch(pathname, init);
const confirmWechatSessionOrigin = async (sessionId) => {
if (!sessionId || confirmedWechatSessionOrigins.has(sessionId)) return;
if (typeof userAuth.setSessionOrigin === 'function') {
try {
await userAuth.setSessionOrigin(sessionId, 'wechat');
} catch (err) {
logger.warn?.('WeChat MP session origin update failed:', err);
return;
}
}
confirmedWechatSessionOrigins.add(sessionId);
};
const enqueueMessageTask = (openid, taskFactory) => {
const key = String(openid ?? '').trim();
const previous = messageTasksByOpenid.get(key) ?? Promise.resolve();
@@ -2038,6 +2053,7 @@ export function createWechatMpService({
sessionPolicy,
).catch(() => false);
if (routeHasTools) {
await confirmWechatSessionOrigin(existingRoute.agentSessionId);
if (typeof userAuth.touchWechatAgentRoute === 'function') {
await userAuth.touchWechatAgentRoute(config.appId, openid, now).catch((err) => {
logger.warn?.('WeChat MP route touch failed:', err);
@@ -2057,7 +2073,12 @@ export function createWechatMpService({
throw new Error(gate.message || '当前用户无法使用聊天能力');
}
const started = startAgentSession
? await startAgentSession({ userId, workingDir, sessionPolicy })
? await startAgentSession({
userId,
workingDir,
sessionPolicy,
origin: 'wechat',
})
: await readJsonResponse(
await apiFetch('/agent/start', {
method: 'POST',
@@ -2094,6 +2115,7 @@ export function createWechatMpService({
origin: 'wechat',
});
}
await confirmWechatSessionOrigin(sessionId);
await reconcileAgentSession(
(pathname, init) => fetchForSession(sessionId, pathname, init),
sessionId,
@@ -2167,7 +2189,14 @@ export function createWechatMpService({
}
};
const buildIntentMetadata = (intent, { mediaAnalysisEnabled = false, imagePolicy = null } = {}) => {
const buildIntentMetadata = (
intent,
{
mediaAnalysisEnabled = false,
imagePolicy = null,
pgRequired = false,
} = {},
) => {
const mediaPublicUrl = intent.media?.publicUrl || null;
const mediaItems = Array.isArray(intent.recentMediaItems) && intent.recentMediaItems.length > 0
? intent.recentMediaItems
@@ -2199,7 +2228,10 @@ export function createWechatMpService({
recognition: intent.msgType === 'voice' ? intent.agentText || null : null,
location: intent.location || null,
link: intent.link || null,
memindRun: buildWechatImageRunMetadata(imagePolicy),
memindRun: {
...buildWechatImageRunMetadata(imagePolicy),
...(pgRequired ? { pgRequired: true } : {}),
},
};
};
@@ -2348,6 +2380,14 @@ export function createWechatMpService({
});
let sessionId = route.sessionId;
await ensureSessionProvider(sessionId);
if (wechatIntent.kind === 'session.reset') {
await sendCustomerServiceText(
inbound.fromUserName,
WECHAT_SESSION_RESET_ACK_TEXT,
user,
);
return { sessionId };
}
await rememberWechatUserContext(sessionId, user, { forceBootstrap: route.isNewSession });
let finished = false;
let progressTimer = null;
@@ -2384,7 +2424,11 @@ export function createWechatMpService({
sessionId,
requestId,
agentPrompt,
buildIntentMetadata(intent, { mediaAnalysisEnabled, imagePolicy }),
buildIntentMetadata(intent, {
mediaAnalysisEnabled,
imagePolicy,
pgRequired: isPageDataRequest,
}),
{
prepareUserMessage: (userMessage) => prepareWechatAgentUserMessage({
userId: user.userId,
@@ -2574,6 +2618,14 @@ export function createWechatMpService({
});
return { sessionId };
} catch (err) {
if (
err &&
typeof err === 'object' &&
sessionId &&
!err.wechatAgentSessionId
) {
err.wechatAgentSessionId = sessionId;
}
const message = err instanceof Error ? err.message : String(err);
if (err?.code === 'WECHAT_AGENT_REPLY_TIMEOUT') {
await userAuth.clearWechatAgentRoute(config.appId, inbound.fromUserName).catch((clearErr) => {
@@ -2628,7 +2680,11 @@ export function createWechatMpService({
sessionId,
retryId,
retryPrompt,
buildIntentMetadata(intent, { mediaAnalysisEnabled, imagePolicy }),
buildIntentMetadata(intent, {
mediaAnalysisEnabled,
imagePolicy,
pgRequired: isPageDataRequest,
}),
{
prepareUserMessage: (userMessage) => prepareWechatAgentUserMessage({
userId: user.userId,
@@ -3284,6 +3340,7 @@ export function createWechatMpService({
openid: inbound.fromUserName,
msgId: inbound.msgId,
status: 'failed',
agentSessionId: err?.wechatAgentSessionId ?? null,
}).catch(() => {});
}
logger.error?.('WeChat MP background reply failed:', err);