Files
memind/wechat-cursor-agent-run.mjs
T
john 644f7fc632
Memind CI / Test, build, and release guards (push) Has been cancelled
fix(wechat): add cursor channel modules required by wechat-mp imports
Ship the WeChat Cursor executor helpers referenced by the page delivery path so tests and runtime imports resolve consistently.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-26 21:14:36 +08:00

118 lines
3.6 KiB
JavaScript

import { buildCodeRunCompletionReply } from './agent-run-gateway.mjs';
import { enforcePageGenerationCursorRuntime } from './cursor-page-routing.mjs';
const DEFAULT_POLL_MS = 2000;
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function buildWechatCursorUserMessage({
displayText,
intentKind,
}) {
const taskText = String(displayText ?? '').trim();
return {
role: 'user',
content: [{ type: 'text', text: taskText }],
metadata: {
displayText: taskText,
memindRun: {
channel: 'wechat_mp',
wechatCursorChannel: true,
taskType: 'wechat_page_generate',
toolMode: 'code',
requiredExecutor: 'cursor',
intentKind: String(intentKind ?? '').trim() || null,
},
},
};
}
async function readCursorCompletionText(agentRunGateway, userId, runId) {
const eventsResult = await agentRunGateway.listRunEventsForUser(userId, runId, { limit: 200 });
const events = Array.isArray(eventsResult?.events) ? eventsResult.events : [];
const resultEvent = [...events].reverse().find((item) => item.eventType === 'tool_gateway_result');
if (!resultEvent?.data) {
return buildCodeRunCompletionReply({ executor: 'cursor', stdout: '' });
}
return buildCodeRunCompletionReply({
executor: resultEvent.data.executor ?? 'cursor',
stdout: resultEvent.data.stdoutTail ?? '',
});
}
export async function executeWechatCursorAgentRun({
agentRunGateway,
userId,
sessionId = null,
requestId,
displayText,
agentPrompt,
intentKind = 'page.generate',
timeoutMs = 15 * 60 * 1000,
pollMs = DEFAULT_POLL_MS,
logger = console,
} = {}) {
if (!agentRunGateway?.createRun || !agentRunGateway?.dispatchRun || !agentRunGateway?.getRunForUser) {
throw Object.assign(new Error('WeChat Cursor 执行网关不可用'), {
code: 'WECHAT_CURSOR_GATEWAY_UNAVAILABLE',
});
}
let userMessage = buildWechatCursorUserMessage({ displayText, intentKind });
const cursorRuntime = enforcePageGenerationCursorRuntime(userMessage, {
rawToolMode: 'code',
taskType: 'wechat_page_generate',
env: process.env,
});
userMessage = cursorRuntime.userMessage;
const run = await agentRunGateway.createRun(userId, {
sessionId,
requestId,
userMessage,
toolMode: 'code',
taskType: cursorRuntime.taskType ?? 'h5_chat_code_task',
});
agentRunGateway.dispatchRun(run.id);
const deadline = Date.now() + Math.max(0, Number(timeoutMs) || 0);
while (Date.now() <= deadline) {
const latest = await agentRunGateway.getRunForUser(userId, run.id);
if (!latest) {
throw Object.assign(new Error('WeChat Cursor 任务丢失'), {
code: 'WECHAT_CURSOR_RUN_MISSING',
});
}
if (latest.status === 'succeeded') {
const text = await readCursorCompletionText(agentRunGateway, userId, run.id);
logger.info?.('[wechat-cursor] run succeeded', {
userId,
runId: run.id,
requestId,
});
return {
text,
tokenState: null,
messages: [{
role: 'assistant',
content: [{ type: 'text', text }],
metadata: { userVisible: true, source: 'wechat-cursor-agent-run' },
}],
requestMessages: [],
};
}
if (latest.status === 'failed') {
const error = new Error(latest.error || 'WeChat Cursor 执行失败');
error.code = 'WECHAT_CURSOR_RUN_FAILED';
throw error;
}
await sleep(Math.max(500, Number(pollMs) || DEFAULT_POLL_MS));
}
throw Object.assign(new Error('WeChat Cursor 执行超时'), {
code: 'WECHAT_CURSOR_RUN_TIMEOUT',
});
}