Add per-feature Cursor channel toggles for admin and runtime.
Memind CI / Test, build, and release guards (push) Has been cancelled
Memind CI / Test, build, and release guards (push) Has been cancelled
Expose page/data/scheduled-task/chat-bridge switches in the智趣体验通道 config so Tang can roll out Cursor paths independently with DeepSeek fallback. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+92
-35
@@ -14,6 +14,8 @@ import {
|
||||
materializeMissingPublicHtmlWrites,
|
||||
} from './mindspace-public-finish-sync.mjs';
|
||||
import { localDateLabel } from './schedule-time.mjs';
|
||||
import { executeCursorChannelCodeRun } from './wechat-cursor-agent-run.mjs';
|
||||
import { resolveCursorScheduledTaskEligible } from './wechat-cursor-executor-policy.mjs';
|
||||
|
||||
function messageText(message) {
|
||||
if (typeof message?.content === 'string') return message.content.trim();
|
||||
@@ -529,6 +531,8 @@ export async function resendScheduledTaskWechatForReadyPage({
|
||||
export async function executeScheduledTask(task, {
|
||||
userAuth,
|
||||
tkmindProxy,
|
||||
agentRunGateway = null,
|
||||
cursorExecutorPolicyService = null,
|
||||
sessionSnapshotService = null,
|
||||
pool = null,
|
||||
h5Root = null,
|
||||
@@ -539,13 +543,6 @@ export async function executeScheduledTask(task, {
|
||||
if (!userAuth || typeof userAuth.canUseChat !== 'function') {
|
||||
throw new Error('缺少 userAuth.canUseChat');
|
||||
}
|
||||
if (
|
||||
!tkmindProxy
|
||||
|| typeof tkmindProxy.startSessionForUser !== 'function'
|
||||
|| typeof tkmindProxy.submitSessionReplyAndAwaitFinishForUser !== 'function'
|
||||
) {
|
||||
throw new Error('缺少 tkmindProxy 会话执行能力');
|
||||
}
|
||||
|
||||
const gate = await userAuth.canUseChat(task.userId);
|
||||
if (!gate?.ok) {
|
||||
@@ -555,38 +552,97 @@ export async function executeScheduledTask(task, {
|
||||
}
|
||||
|
||||
const requestId = crypto.randomUUID();
|
||||
const started = await tkmindProxy.startSessionForUser(task.userId, {
|
||||
origin: 'h5',
|
||||
});
|
||||
const sessionId = started?.id ?? started?.sessionId;
|
||||
if (!sessionId) throw new Error('创建定时任务会话失败');
|
||||
|
||||
const userMessage = buildScheduledTaskExecutionPrompt(task);
|
||||
logger.info?.('[ScheduledTask] executing', {
|
||||
taskId: task.id,
|
||||
userId: task.userId,
|
||||
sessionId,
|
||||
requestId,
|
||||
});
|
||||
|
||||
await tkmindProxy.submitSessionReplyAndAwaitFinishForUser(
|
||||
task.userId,
|
||||
sessionId,
|
||||
requestId,
|
||||
userMessage,
|
||||
{ timeoutMs },
|
||||
);
|
||||
|
||||
let messages = await refreshScheduledTaskMessages({
|
||||
userId: task.userId,
|
||||
sessionId,
|
||||
tkmindProxy,
|
||||
sessionSnapshotService,
|
||||
});
|
||||
|
||||
const publishDir = h5Root && task.userId
|
||||
? path.join(h5Root, 'MindSpace', task.userId)
|
||||
: null;
|
||||
|
||||
let cursorPolicy = null;
|
||||
let useCursorPath = false;
|
||||
if (agentRunGateway && cursorExecutorPolicyService?.getEffectivePolicy) {
|
||||
try {
|
||||
cursorPolicy = await cursorExecutorPolicyService.getEffectivePolicy(task.userId, {
|
||||
userId: task.userId,
|
||||
});
|
||||
useCursorPath = resolveCursorScheduledTaskEligible({
|
||||
user: { userId: task.userId },
|
||||
policy: cursorPolicy,
|
||||
});
|
||||
} catch (err) {
|
||||
logger.warn?.('[ScheduledTask] cursor policy lookup failed:', err);
|
||||
}
|
||||
}
|
||||
|
||||
let sessionId = null;
|
||||
let messages = [];
|
||||
|
||||
if (useCursorPath) {
|
||||
logger.info?.('[ScheduledTask] executing via cursor channel', {
|
||||
taskId: task.id,
|
||||
userId: task.userId,
|
||||
requestId,
|
||||
});
|
||||
try {
|
||||
const cursorResult = await executeCursorChannelCodeRun({
|
||||
agentRunGateway,
|
||||
userId: task.userId,
|
||||
requestId,
|
||||
displayText: `定时任务:${task.title}`,
|
||||
agentPrompt: userMessage.content[0]?.text ?? userMessage.content,
|
||||
intentKind: 'page.generate',
|
||||
channel: 'scheduled_task',
|
||||
taskType: 'h5_chat_code_task',
|
||||
policy: cursorPolicy,
|
||||
forceCursorExecutor: true,
|
||||
timeoutMs,
|
||||
logger,
|
||||
});
|
||||
messages = cursorResult.messages ?? [];
|
||||
sessionId = cursorResult.runId ?? null;
|
||||
} catch (cursorErr) {
|
||||
if (cursorPolicy?.fallbackToDeepseek === false) throw cursorErr;
|
||||
logger.warn?.('[ScheduledTask] cursor execution failed, falling back to goose:', cursorErr);
|
||||
useCursorPath = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!useCursorPath) {
|
||||
if (
|
||||
!tkmindProxy
|
||||
|| typeof tkmindProxy.startSessionForUser !== 'function'
|
||||
|| typeof tkmindProxy.submitSessionReplyAndAwaitFinishForUser !== 'function'
|
||||
) {
|
||||
throw new Error('缺少 tkmindProxy 会话执行能力');
|
||||
}
|
||||
const started = await tkmindProxy.startSessionForUser(task.userId, {
|
||||
origin: 'h5',
|
||||
});
|
||||
sessionId = started?.id ?? started?.sessionId;
|
||||
if (!sessionId) throw new Error('创建定时任务会话失败');
|
||||
|
||||
logger.info?.('[ScheduledTask] executing via goose session', {
|
||||
taskId: task.id,
|
||||
userId: task.userId,
|
||||
sessionId,
|
||||
requestId,
|
||||
});
|
||||
|
||||
await tkmindProxy.submitSessionReplyAndAwaitFinishForUser(
|
||||
task.userId,
|
||||
sessionId,
|
||||
requestId,
|
||||
userMessage,
|
||||
{ timeoutMs },
|
||||
);
|
||||
|
||||
messages = await refreshScheduledTaskMessages({
|
||||
userId: task.userId,
|
||||
sessionId,
|
||||
tkmindProxy,
|
||||
sessionSnapshotService,
|
||||
});
|
||||
}
|
||||
|
||||
let deliveryText = extractScheduledTaskDeliveryText(messages, task);
|
||||
const deliveryResult = publishDir
|
||||
? await awaitScheduledTaskPageDelivery({
|
||||
@@ -624,5 +680,6 @@ export async function executeScheduledTask(task, {
|
||||
deliveryText,
|
||||
messages,
|
||||
readyPaths,
|
||||
executor: useCursorPath ? 'cursor' : 'goose',
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user