Skip Cursor Chat Bridge for WeChat MP and page.generate sessions.
Memind CI / Test, build, and release guards (push) Failing after 5m45s
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:
+3
-1
@@ -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;
|
if (!llmProviderService || !sessionId) return null;
|
||||||
try {
|
try {
|
||||||
const target = await resolveTarget(sessionId);
|
const target = await resolveTarget(sessionId);
|
||||||
@@ -1617,6 +1617,8 @@ export function createTkmindProxy({
|
|||||||
if (
|
if (
|
||||||
resolveCursorChatBridgeEligible({
|
resolveCursorChatBridgeEligible({
|
||||||
user: { userId },
|
user: { userId },
|
||||||
|
channel,
|
||||||
|
intentKind,
|
||||||
policy: cursorPolicy,
|
policy: cursorPolicy,
|
||||||
})
|
})
|
||||||
&& typeof llmProviderService.applyCursorChatBridgeForSession === 'function'
|
&& typeof llmProviderService.applyCursorChatBridgeForSession === 'function'
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ export function resolveCursorChannelEligible({
|
|||||||
export function resolveCursorChatBridgeEligible({
|
export function resolveCursorChatBridgeEligible({
|
||||||
user = null,
|
user = null,
|
||||||
userId = null,
|
userId = null,
|
||||||
|
channel = '',
|
||||||
|
intentKind = '',
|
||||||
policy = null,
|
policy = null,
|
||||||
env = process.env,
|
env = process.env,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
@@ -37,6 +39,13 @@ export function resolveCursorChatBridgeEligible({
|
|||||||
const subject = user ?? { userId };
|
const subject = user ?? { userId };
|
||||||
if (!isUserAllowedByWechatCursorPolicy(subject, policy)) return false;
|
if (!isUserAllowedByWechatCursorPolicy(subject, policy)) return false;
|
||||||
if (!isCursorFeatureEnabled(policy, CURSOR_CHANNEL_FEATURES.CHAT_BRIDGE)) 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();
|
const bridgeEnvEnabled = String(env?.MEMIND_CURSOR_CHAT_BRIDGE_ENABLED ?? '').trim();
|
||||||
if (!['1', 'true', 'yes', 'on'].includes(bridgeEnvEnabled.toLowerCase())) return false;
|
if (!['1', 'true', 'yes', 'on'].includes(bridgeEnvEnabled.toLowerCase())) return false;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
CURSOR_EXECUTOR_CHANNEL,
|
CURSOR_EXECUTOR_CHANNEL,
|
||||||
resolveCursorChannelEligible,
|
resolveCursorChannelEligible,
|
||||||
|
resolveCursorChatBridgeEligible,
|
||||||
resolveCursorScheduledTaskEligible,
|
resolveCursorScheduledTaskEligible,
|
||||||
resolveWechatCursorExecutorEligible,
|
resolveWechatCursorExecutorEligible,
|
||||||
} from './wechat-cursor-executor-policy.mjs';
|
} 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', () => {
|
test('isChannelAllowedByCursorPolicy defaults to both channels', () => {
|
||||||
const policy = { channelAllowlist: ['h5', 'wechat_mp'] };
|
const policy = { channelAllowlist: ['h5', 'wechat_mp'] };
|
||||||
assert.equal(isChannelAllowedByCursorPolicy('h5', policy), true);
|
assert.equal(isChannelAllowedByCursorPolicy('h5', policy), true);
|
||||||
|
|||||||
+9
-5
@@ -2179,9 +2179,13 @@ export function createWechatMpService({
|
|||||||
throw notifyFailure ? markWechatUserNotified(error) : error;
|
throw notifyFailure ? markWechatUserNotified(error) : error;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ensureSessionProvider = async (sessionId, userId = null) => {
|
const ensureSessionProvider = async (sessionId, userId = null, { intentKind = '' } = {}) => {
|
||||||
if (!applySessionLlmProvider || !sessionId) return;
|
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) {
|
if (applied && applied.ok === false) {
|
||||||
throw new Error(applied.message || '专属 Agent Provider 未配置');
|
throw new Error(applied.message || '专属 Agent Provider 未配置');
|
||||||
}
|
}
|
||||||
@@ -2823,7 +2827,7 @@ export function createWechatMpService({
|
|||||||
});
|
});
|
||||||
let sessionId = route.sessionId;
|
let sessionId = route.sessionId;
|
||||||
let carriedSessionContent = String(route.carriedSessionContent ?? '').trim();
|
let carriedSessionContent = String(route.carriedSessionContent ?? '').trim();
|
||||||
await ensureSessionProvider(sessionId, user.userId);
|
await ensureSessionProvider(sessionId, user.userId, { intentKind: wechatIntent.kind });
|
||||||
if (wechatIntent.kind === 'session.reset') {
|
if (wechatIntent.kind === 'session.reset') {
|
||||||
await sendCustomerServiceText(
|
await sendCustomerServiceText(
|
||||||
inbound.fromUserName,
|
inbound.fromUserName,
|
||||||
@@ -2850,7 +2854,7 @@ export function createWechatMpService({
|
|||||||
if (pollutionRotation.carriedSessionContent) {
|
if (pollutionRotation.carriedSessionContent) {
|
||||||
carriedSessionContent = pollutionRotation.carriedSessionContent;
|
carriedSessionContent = pollutionRotation.carriedSessionContent;
|
||||||
}
|
}
|
||||||
await ensureSessionProvider(sessionId, user.userId);
|
await ensureSessionProvider(sessionId, user.userId, { intentKind: wechatIntent.kind });
|
||||||
await rememberWechatUserContext(sessionId, user, { forceBootstrap: true });
|
await rememberWechatUserContext(sessionId, user, { forceBootstrap: true });
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
@@ -3392,7 +3396,7 @@ export function createWechatMpService({
|
|||||||
userContext: user,
|
userContext: user,
|
||||||
});
|
});
|
||||||
sessionId = route.sessionId;
|
sessionId = route.sessionId;
|
||||||
await ensureSessionProvider(sessionId, user.userId);
|
await ensureSessionProvider(sessionId, user.userId, { intentKind: wechatIntent.kind });
|
||||||
await rememberWechatUserContext(sessionId, user, { forceBootstrap: route.isNewSession });
|
await rememberWechatUserContext(sessionId, user, { forceBootstrap: route.isNewSession });
|
||||||
if (historicalImageError) {
|
if (historicalImageError) {
|
||||||
prepareWechatIntentForHistoricalImageRetry(intent, {
|
prepareWechatIntentForHistoricalImageRetry(intent, {
|
||||||
|
|||||||
Reference in New Issue
Block a user