import { AIDER_DEVELOPMENT_SKILL_NAME, EXCEL_ANALYST_SKILL_NAME, PAGE_DATA_COLLECT_SKILL_NAME, extractAiderDevelopmentTask, isExcelAnalysisIntent, isGenericPageGenerationRequest, isPageDataDevIntent, isPageDataIntent, isPageGenerationIntent, } from './chat-skills.mjs'; import { cursorAgentTasksDefaultEnabled, cursorExecutorEnabled, cursorPageTasksDefaultEnabled, resolvePreferredCodeExecutor, } from './cursor-agent-launch.mjs'; const PUBLISH_SKILL_NAME = 'static-page-publish'; const PAGE_CURSOR_TASK_TYPE = 'h5_chat_code_task'; const CURSOR_TASK_KIND = { PAGE_GENERATION: 'page_generation', PAGE_DATA: 'page_data', EXCEL_ANALYSIS: 'excel_analysis', }; function selectedChatSkill(userMessage) { const metadata = userMessage?.metadata; const runMetadata = metadata?.memindRun ?? metadata?.agentRun ?? {}; return String(runMetadata.selectedChatSkill ?? '').trim(); } export function resolveCursorTaskKind(taskText, skill = '') { const normalized = String(taskText ?? '').trim(); if (!normalized || isPageDataDevIntent(normalized)) return null; const selectedSkill = String(skill ?? '').trim(); if ( selectedSkill === PAGE_DATA_COLLECT_SKILL_NAME || isPageDataIntent(normalized) ) { return CURSOR_TASK_KIND.PAGE_DATA; } if ( selectedSkill === EXCEL_ANALYST_SKILL_NAME || isExcelAnalysisIntent(normalized) ) { return CURSOR_TASK_KIND.EXCEL_ANALYSIS; } if ( selectedSkill === PUBLISH_SKILL_NAME || isPageGenerationIntent(normalized) ) { if (isGenericPageGenerationRequest(normalized)) return null; return CURSOR_TASK_KIND.PAGE_GENERATION; } return null; } export function isPageCursorDefaultCandidate(userMessage, { rawToolMode = 'chat', env = process.env, channelEligible = false, } = {}) { if (!cursorExecutorEnabled(env)) return false; if (!channelEligible) return false; if (String(rawToolMode ?? '').trim().toLowerCase() === 'code') return false; const skill = selectedChatSkill(userMessage); if (skill === AIDER_DEVELOPMENT_SKILL_NAME) return false; const runMetadata = userMessage?.metadata?.memindRun ?? userMessage?.metadata?.agentRun ?? {}; if (runMetadata.pageTemplateSkill || runMetadata.pageTemplateStrict) return false; const taskText = extractAiderDevelopmentTask(userMessage); if (!taskText) return false; return resolveCursorTaskKind(taskText, skill) !== null; } function buildCursorPageInstruction(taskText) { return [ taskText, '', '[Memind page task via TKMind 智趣 executor]', '在当前用户 MindSpace 工作区生成或更新 public/*.html 页面。', '完成后确保页面可通过 /MindSpace//public/.html 访问。', '不要只回复文字,必须实际落盘 HTML 文件。', ].join('\n'); } function buildCursorPageDataInstruction(taskText) { return [ taskText, '', '[Memind Page Data survey task via TKMind 智趣 executor]', '在当前用户 MindSpace 工作区完成可提交、可持久化的问卷/数据收集与结果分析页面。', '必须先阅读 docs/page-data-api-usage.md 与 docs/examples/page-data-survey-test.md。', '需要:1) 创建/更新 public/*.html 问卷页(含 MindSpacePageData.createClient);', '2) 按需创建后台分析页;3) 注册 dataset 与 page policy(可参考 scripts/setup-page-data-survey-demo.mjs);', '4) 数据必须持久化到 PG(通过 Page Data API),不要旁路自建 API。', '完成后确保页面可通过 /MindSpace//public/.html 访问。', '不要只回复文字,必须实际落盘 HTML 与相关配置文件。', ].join('\n'); } function buildCursorExcelInstruction(taskText) { return [ taskText, '', '[Memind Excel analysis task via TKMind 智趣 executor]', '在当前用户 MindSpace 工作区分析用户上传的 Excel/CSV 等表格文件。', '先在工作区 attachments/、uploads/ 或用户消息提及的路径定位附件文件,读取并分析数据。', '输出分析结论,并生成可访问的结果页面 public/*.html 或分析报告文件。', '不要只回复文字,必须实际读取文件并产出可交付结果。', ].join('\n'); } function buildCursorTaskInstruction(taskText, taskKind) { switch (taskKind) { case CURSOR_TASK_KIND.PAGE_DATA: return buildCursorPageDataInstruction(taskText); case CURSOR_TASK_KIND.EXCEL_ANALYSIS: return buildCursorExcelInstruction(taskText); case CURSOR_TASK_KIND.PAGE_GENERATION: default: return buildCursorPageInstruction(taskText); } } function resolveCursorTaskSkill(taskKind, runMetadataSkill = '') { const existing = String(runMetadataSkill ?? '').trim(); if (existing && existing !== AIDER_DEVELOPMENT_SKILL_NAME) return existing; switch (taskKind) { case CURSOR_TASK_KIND.PAGE_DATA: return PAGE_DATA_COLLECT_SKILL_NAME; case CURSOR_TASK_KIND.EXCEL_ANALYSIS: return EXCEL_ANALYST_SKILL_NAME; case CURSOR_TASK_KIND.PAGE_GENERATION: default: return PUBLISH_SKILL_NAME; } } function resolveCursorSuggestedDelivery(taskKind) { switch (taskKind) { case CURSOR_TASK_KIND.PAGE_DATA: return 'mindspace_page_data'; case CURSOR_TASK_KIND.EXCEL_ANALYSIS: return 'mindspace_analysis_html'; case CURSOR_TASK_KIND.PAGE_GENERATION: default: return 'mindspace_public_html'; } } function rewriteUserMessageForCursorTask(userMessage, taskText, taskKind) { const message = userMessage && typeof userMessage === 'object' && !Array.isArray(userMessage) ? { ...userMessage } : { value: userMessage }; const metadata = message.metadata && typeof message.metadata === 'object' && !Array.isArray(message.metadata) ? { ...message.metadata } : {}; const instruction = buildCursorTaskInstruction(taskText, taskKind); metadata.displayText = taskText; metadata.userVisible = true; const content = Array.isArray(message.content) ? message.content.map((item) => ( item?.type === 'text' ? { ...item, text: instruction } : item )) : [{ type: 'text', text: instruction }]; return { ...message, metadata, content }; } export function enforcePageGenerationCursorRuntime(userMessage, { rawToolMode = 'chat', taskType = null, forceDeepReasoning = false, env = process.env, channelEligible = false, } = {}) { if (!isPageCursorDefaultCandidate(userMessage, { rawToolMode, env, channelEligible })) { return { userMessage, rawToolMode, taskType, forceDeepReasoning, requiredExecutor: null, }; } const taskText = extractAiderDevelopmentTask(userMessage); const skill = selectedChatSkill(userMessage); const taskKind = resolveCursorTaskKind(taskText, skill); if (!taskKind) { return { userMessage, rawToolMode, taskType, forceDeepReasoning, requiredExecutor: null, }; } const codeExecutor = resolvePreferredCodeExecutor(env); const message = rewriteUserMessageForCursorTask(userMessage, taskText, taskKind); const metadata = message.metadata && typeof message.metadata === 'object' && !Array.isArray(message.metadata) ? { ...message.metadata } : {}; const runMetadata = metadata.memindRun && typeof metadata.memindRun === 'object' && !Array.isArray(metadata.memindRun) ? { ...metadata.memindRun } : {}; metadata.memindRun = { ...runMetadata, executor: codeExecutor, pageCursorDefault: true, cursorTaskKind: taskKind, cursorChannel: true, channel: 'h5', suggestedDelivery: resolveCursorSuggestedDelivery(taskKind), selectedChatSkill: resolveCursorTaskSkill(taskKind, runMetadata.selectedChatSkill), }; return { userMessage: { ...message, metadata }, rawToolMode: 'code', taskType: PAGE_CURSOR_TASK_TYPE, forceDeepReasoning: true, requiredExecutor: codeExecutor, }; } export function applyCursorFirstAgentExecution(userMessage, runOptions = {}, { routingDecision = null, env = process.env, } = {}) { // Cursor 仅服务于显式页面/代码任务(enforcePageGenerationCursorRuntime)。 // 普通 Agent 编排走 Goose/DeepSeek,不因 MEMIND_CURSOR_AGENT_TASKS_DEFAULT 全量切 Cursor。 void userMessage; void runOptions; void routingDecision; void env; return { userMessage, runOptions, cursorFirst: false }; } export function __cursorPageRoutingTestExports() { return { PAGE_CURSOR_TASK_TYPE, CURSOR_TASK_KIND, cursorPageTasksDefaultEnabled, cursorAgentTasksDefaultEnabled, }; }