Fix scheduled task page delivery unlock and notification links.
Memind CI / Test, build, and release guards (push) Failing after 5s

Finalize page delivery contracts after worker execution, fetch session messages via tkmindProxy, and append public page URLs to WeChat notifications.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-07-31 09:06:07 +08:00
parent 6acd79e4fa
commit 005612029f
3 changed files with 97 additions and 4 deletions
+91 -4
View File
@@ -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,
};
}
+4
View File
@@ -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,
});
@@ -286,6 +286,8 @@ export async function bootstrapPortalIntegrationServices({
tkmindProxy,
sessionSnapshotService,
notificationDispatcher,
pool,
h5Root,
logger,
});
logger.log('Scheduled task worker enabled');