Skip Cursor Chat Bridge for WeChat MP and page.generate sessions.
Memind CI / Test, build, and release guards (push) Failing after 5m45s

WeChat Goose turns always include tools, which the bridge PoC rejects with HTTP 501; keep Kimi/DeepSeek on the session while Cursor handles page execution separately.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-08-31 10:16:03 +08:00
parent 3688d732c0
commit fa20f735a5
4 changed files with 65 additions and 6 deletions
+3 -1
View File
@@ -1602,7 +1602,7 @@ export function createTkmindProxy({
}
}
async function applySessionLlmProvider(sessionId, { userId = null } = {}) {
async function applySessionLlmProvider(sessionId, { userId = null, channel = 'h5', intentKind = '' } = {}) {
if (!llmProviderService || !sessionId) return null;
try {
const target = await resolveTarget(sessionId);
@@ -1617,6 +1617,8 @@ export function createTkmindProxy({
if (
resolveCursorChatBridgeEligible({
user: { userId },
channel,
intentKind,
policy: cursorPolicy,
})
&& typeof llmProviderService.applyCursorChatBridgeForSession === 'function'
+9
View File
@@ -30,6 +30,8 @@ export function resolveCursorChannelEligible({
export function resolveCursorChatBridgeEligible({
user = null,
userId = null,
channel = '',
intentKind = '',
policy = null,
env = process.env,
} = {}) {
@@ -37,6 +39,13 @@ export function resolveCursorChatBridgeEligible({
const subject = user ?? { userId };
if (!isUserAllowedByWechatCursorPolicy(subject, policy)) return false;
if (!isCursorFeatureEnabled(policy, CURSOR_CHANNEL_FEATURES.CHAT_BRIDGE)) return false;
const normalizedChannel = String(channel ?? '').trim().toLowerCase();
// WeChat Goose sessions always carry tools; the bridge PoC rejects tool calls.
if (normalizedChannel === CURSOR_EXECUTOR_CHANNEL.WECHAT_MP) return false;
if (String(intentKind ?? '').trim() === 'page.generate') return false;
if (!isChannelAllowedByCursorPolicy(normalizedChannel || CURSOR_EXECUTOR_CHANNEL.H5, policy)) {
return false;
}
const bridgeEnvEnabled = String(env?.MEMIND_CURSOR_CHAT_BRIDGE_ENABLED ?? '').trim();
if (!['1', 'true', 'yes', 'on'].includes(bridgeEnvEnabled.toLowerCase())) return false;
return true;
+44
View File
@@ -9,6 +9,7 @@ import {
import {
CURSOR_EXECUTOR_CHANNEL,
resolveCursorChannelEligible,
resolveCursorChatBridgeEligible,
resolveCursorScheduledTaskEligible,
resolveWechatCursorExecutorEligible,
} from './wechat-cursor-executor-policy.mjs';
@@ -178,6 +179,49 @@ test('H5 channel respects channelAllowlist', async () => {
);
});
test('resolveCursorChatBridgeEligible is disabled for WeChat MP and page.generate', async () => {
const pool = createMemoryPool();
const service = createWechatCursorExecutorAdminConfigService(pool);
await service.updateAdminConfig({
enabled: true,
userAllowlist: ['john-uuid'],
features: {
pageGenerate: { enabled: true },
chatBridge: { enabled: true },
},
}, { updatedBy: 'admin-1' });
const policy = await service.getEffectivePolicy('john-uuid', { userId: 'john-uuid' });
assert.equal(
resolveCursorChatBridgeEligible({
user: { userId: 'john-uuid' },
channel: CURSOR_EXECUTOR_CHANNEL.WECHAT_MP,
policy,
env: { MEMIND_CURSOR_CHAT_BRIDGE_ENABLED: '1' },
}),
false,
);
assert.equal(
resolveCursorChatBridgeEligible({
user: { userId: 'john-uuid' },
channel: CURSOR_EXECUTOR_CHANNEL.H5,
intentKind: 'page.generate',
policy,
env: { MEMIND_CURSOR_CHAT_BRIDGE_ENABLED: '1' },
}),
false,
);
assert.equal(
resolveCursorChatBridgeEligible({
user: { userId: 'john-uuid' },
channel: CURSOR_EXECUTOR_CHANNEL.H5,
intentKind: 'chat.general',
policy,
env: { MEMIND_CURSOR_CHAT_BRIDGE_ENABLED: '1' },
}),
true,
);
});
test('isChannelAllowedByCursorPolicy defaults to both channels', () => {
const policy = { channelAllowlist: ['h5', 'wechat_mp'] };
assert.equal(isChannelAllowedByCursorPolicy('h5', policy), true);
+9 -5
View File
@@ -2179,9 +2179,13 @@ export function createWechatMpService({
throw notifyFailure ? markWechatUserNotified(error) : error;
};
const ensureSessionProvider = async (sessionId, userId = null) => {
const ensureSessionProvider = async (sessionId, userId = null, { intentKind = '' } = {}) => {
if (!applySessionLlmProvider || !sessionId) return;
const applied = await applySessionLlmProvider(sessionId, { userId });
const applied = await applySessionLlmProvider(sessionId, {
userId,
channel: 'wechat_mp',
intentKind,
});
if (applied && applied.ok === false) {
throw new Error(applied.message || '专属 Agent Provider 未配置');
}
@@ -2823,7 +2827,7 @@ export function createWechatMpService({
});
let sessionId = route.sessionId;
let carriedSessionContent = String(route.carriedSessionContent ?? '').trim();
await ensureSessionProvider(sessionId, user.userId);
await ensureSessionProvider(sessionId, user.userId, { intentKind: wechatIntent.kind });
if (wechatIntent.kind === 'session.reset') {
await sendCustomerServiceText(
inbound.fromUserName,
@@ -2850,7 +2854,7 @@ export function createWechatMpService({
if (pollutionRotation.carriedSessionContent) {
carriedSessionContent = pollutionRotation.carriedSessionContent;
}
await ensureSessionProvider(sessionId, user.userId);
await ensureSessionProvider(sessionId, user.userId, { intentKind: wechatIntent.kind });
await rememberWechatUserContext(sessionId, user, { forceBootstrap: true });
}
if (
@@ -3392,7 +3396,7 @@ export function createWechatMpService({
userContext: user,
});
sessionId = route.sessionId;
await ensureSessionProvider(sessionId, user.userId);
await ensureSessionProvider(sessionId, user.userId, { intentKind: wechatIntent.kind });
await rememberWechatUserContext(sessionId, user, { forceBootstrap: route.isNewSession });
if (historicalImageError) {
prepareWechatIntentForHistoricalImageRetry(intent, {