fix: retain unlinked WeChat route for immediate-context page requests
Memind CI / Test, build, and release guards (push) Successful in 20m49s

Short follow-ups like "把刚才的诗做成页面" must keep the existing agent
session so Goose still sees the adjacent poem in snapshot history. Rotating
orphan routes before these requests dropped the poem and revived stale memory.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-07-28 14:38:53 +08:00
parent b10f0a7600
commit e1ad094f93
2 changed files with 73 additions and 2 deletions
+6 -2
View File
@@ -1984,6 +1984,7 @@ export function createWechatMpService({
userId,
openid,
forceNew = false,
retainUnlinkedRoute = false,
userContext = null,
}) => {
if (forceNew) {
@@ -2045,8 +2046,10 @@ export function createWechatMpService({
snapshotMessageCount: routeSnapshotMessageCount,
now,
});
if (routeIsIdle || routeIsTooLong || routeHasUnlinkedConversation) {
if (routeHasUnlinkedConversation) {
const shouldRotateUnlinkedRoute =
routeHasUnlinkedConversation && !retainUnlinkedRoute;
if (routeIsIdle || routeIsTooLong || shouldRotateUnlinkedRoute) {
if (shouldRotateUnlinkedRoute) {
logger.warn?.('WeChat MP orphaned route rotated before reuse:', {
agentSessionId: existingRoute.agentSessionId,
snapshotMessageCount: routeSnapshotMessageCount,
@@ -2439,6 +2442,7 @@ export function createWechatMpService({
openid: inbound.fromUserName,
userContext: user,
forceNew,
retainUnlinkedRoute: immediateContextFollowup,
});
let sessionId = route.sessionId;
await ensureSessionProvider(sessionId);
+67
View File
@@ -358,6 +358,73 @@ test('WeChat immediate-context page guard does not match complete page requests'
assert.doesNotMatch(ordinaryPrompt, /即时上下文优先/);
});
test('WeChat immediate-context page retains an unlinked route with adjacent snapshot', async () => {
const clearedRoutes = [];
const startedSessions = [];
let activeRoute = {
agentSessionId: 'session-poem',
updatedAt: Date.now() - 120_000,
};
const service = createBoundWechatService({
config: {
sessionMessageRotateCount: 0,
sessionIdleRotateMs: 0,
},
userAuth: {
async getWechatAgentRoute() {
return activeRoute;
},
async clearWechatAgentRoute(_appId, openid) {
clearedRoutes.push(openid);
activeRoute = null;
},
async countWechatAgentSessionMessages() {
return 0;
},
async getWechatAgentSessionSnapshotMessageCount() {
return 5;
},
async touchWechatAgentRoute(_appId, _openid, updatedAt) {
activeRoute = { ...activeRoute, updatedAt };
},
},
startAgentSession: async (sessionId) => {
startedSessions.push(sessionId);
return sessionId;
},
sessionApiFetch: async (pathname) => {
if (String(pathname).includes('/tools')) {
return new Response(JSON.stringify({ tools: [] }), {
status: 200,
headers: { 'Content-Type': 'application/json' },
});
}
return new Response(JSON.stringify({ conversation: [] }), {
status: 200,
headers: { 'Content-Type': 'application/json' },
});
},
submitSessionReply: async () => ({
ok: true,
conversation: [{ role: 'assistant', content: [{ type: 'text', text: 'ok' }] }],
}),
});
const timestamp = '1710000000';
const nonce = 'nonce-immediate-context-route';
await service.handleInboundMessage(
inboundXml({ content: '把刚才的诗做成页面' }),
{
timestamp,
nonce,
signature: signatureFor('token', timestamp, nonce),
},
);
assert.equal(clearedRoutes.length, 0);
assert.equal(startedSessions.length, 0);
});
test('WeChat only rotates an aged route with conversation but no linked inbound message', () => {
const now = 200_000;
assert.equal(