From 005612029f1ce75e89e9e4448d410d66e7ed3cf2 Mon Sep 17 00:00:00 2001 From: john Date: Fri, 31 Jul 2026 09:06:07 +0800 Subject: [PATCH] Fix scheduled task page delivery unlock and notification links. Finalize page delivery contracts after worker execution, fetch session messages via tkmindProxy, and append public page URLs to WeChat notifications. Co-authored-by: Cursor --- scheduled-task-executor.mjs | 95 ++++++++++++++++++- scheduled-task-worker.mjs | 4 + .../portal-integration-services-bootstrap.mjs | 2 + 3 files changed, 97 insertions(+), 4 deletions(-) diff --git a/scheduled-task-executor.mjs b/scheduled-task-executor.mjs index 3c538ee..f9db16a 100644 --- a/scheduled-task-executor.mjs +++ b/scheduled-task-executor.mjs @@ -1,5 +1,11 @@ import crypto from 'node:crypto'; +import path from 'node:path'; import { buildChatSkillPrompt, SCHEDULED_TASK_AUTOMATION_SKILL_NAME } from './chat-skills.mjs'; +import { markPageDeliveryContractReady } from './mindspace-delivery-contract.mjs'; +import { + collectOwnPublicHtmlRelativePaths, + materializeMissingPublicHtmlWrites, +} from './mindspace-public-finish-sync.mjs'; import { localDateLabel } from './schedule-time.mjs'; function messageText(message) { @@ -63,10 +69,65 @@ export function formatScheduledTaskDeliveryMessage(task, deliveryText) { return `${header}\n\n${body}`.trim(); } +export async function finalizeScheduledTaskPageDelivery({ + pool, + userId, + sessionId, + messages, + publishDir, + currentUser = null, + logger = console, +} = {}) { + if (!pool || !userId || !publishDir) return []; + + const materialized = materializeMissingPublicHtmlWrites({ messages, publishDir }); + const relativePaths = new Set( + collectOwnPublicHtmlRelativePaths({ + messages, + currentUser: currentUser ?? { id: userId }, + publishDir, + materialized: materialized.materialized, + skipped: materialized.skipped, + }), + ); + + if (sessionId) { + const [rows] = await pool.query( + `SELECT workspace_relative_path + FROM h5_page_delivery_contracts + WHERE user_id = ? AND request_id = ? AND status = 'preparing'`, + [userId, sessionId], + ); + for (const row of rows ?? []) { + if (row?.workspace_relative_path) relativePaths.add(row.workspace_relative_path); + } + } + + const readyPaths = []; + for (const relativePath of relativePaths) { + const ready = await markPageDeliveryContractReady({ + pool, + userId, + relativePath, + }).catch(() => false); + if (ready) readyPaths.push(relativePath); + else { + logger.warn?.('[ScheduledTask] delivery contract not ready', { + userId, + sessionId, + relativePath, + }); + } + } + return readyPaths; +} + export async function executeScheduledTask(task, { userAuth, tkmindProxy, sessionSnapshotService = null, + pool = null, + h5Root = null, timeoutMs = 15 * 60 * 1000, logger = console, } = {}) { @@ -113,19 +174,45 @@ export async function executeScheduledTask(task, { ); let messages = []; - if (typeof sessionSnapshotService?.refresh === 'function') { - const refreshed = await sessionSnapshotService.refresh(sessionId).catch(() => null); - messages = refreshed?.messages ?? refreshed?.conversation?.messages ?? []; + if (typeof tkmindProxy.fetchSessionConversationForUser === 'function') { + messages = await tkmindProxy.fetchSessionConversationForUser(task.userId, sessionId).catch(() => []); } else if (typeof sessionSnapshotService?.get === 'function') { const snapshot = await sessionSnapshotService.get(sessionId).catch(() => null); messages = snapshot?.messages ?? snapshot?.conversation?.messages ?? []; } - const deliveryText = extractScheduledTaskDeliveryText(messages, task); + const publishDir = h5Root && task.userId + ? path.join(h5Root, 'MindSpace', task.userId) + : null; + const readyPaths = await finalizeScheduledTaskPageDelivery({ + pool, + userId: task.userId, + sessionId, + messages, + publishDir, + logger, + }).catch((error) => { + logger.warn?.('[ScheduledTask] finalize page delivery failed:', error); + return []; + }); + + let deliveryText = extractScheduledTaskDeliveryText(messages, task); + if ( + readyPaths.length > 0 + && !/https?:\/\//i.test(deliveryText) + && task.userId + ) { + const links = readyPaths.map( + (relativePath) => `https://m.tkmind.cn/MindSpace/${task.userId}/${relativePath}`, + ); + deliveryText = `${deliveryText}\n\n页面链接:\n${links.join('\n')}`.trim(); + } + return { sessionId, requestId, deliveryText, messages, + readyPaths, }; } diff --git a/scheduled-task-worker.mjs b/scheduled-task-worker.mjs index 4482038..c1d1e88 100644 --- a/scheduled-task-worker.mjs +++ b/scheduled-task-worker.mjs @@ -11,6 +11,8 @@ export function startScheduledTaskWorker({ tkmindProxy = null, sessionSnapshotService = null, notificationDispatcher = null, + pool = null, + h5Root = null, logger = console, intervalMs = Number(process.env.H5_SCHEDULED_TASK_SCAN_INTERVAL_MS ?? 30_000), maxAttempts = Number(process.env.H5_SCHEDULED_TASK_MAX_ATTEMPTS ?? 3), @@ -70,6 +72,8 @@ export function startScheduledTaskWorker({ userAuth, tkmindProxy, sessionSnapshotService, + pool, + h5Root, timeoutMs: executionTimeoutMs, logger, }); diff --git a/server/portal-integration-services-bootstrap.mjs b/server/portal-integration-services-bootstrap.mjs index b38466e..0107aa6 100644 --- a/server/portal-integration-services-bootstrap.mjs +++ b/server/portal-integration-services-bootstrap.mjs @@ -286,6 +286,8 @@ export async function bootstrapPortalIntegrationServices({ tkmindProxy, sessionSnapshotService, notificationDispatcher, + pool, + h5Root, logger, }); logger.log('Scheduled task worker enabled');