Files
memind/scheduled-task-executor.test.mjs
T
john 1d165bc6e3 feat(goose): complete v1.49 phase3 closeout gates and context fusion plan
Expand Goose v1.49 smoke coverage (memory chat, portal resume, page e2e,
multiturn provider), add canary memory policy lock, refresh baselines, and
ignore one-off evidence artifacts. Document headroom-based context runtime
fusion plan; include auth, scheduled-task, and wechat intent fixes on branch.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-09 18:11:39 +08:00

273 lines
9.2 KiB
JavaScript

import assert from 'node:assert/strict';
import fs from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import test from 'node:test';
import {
buildScheduledTaskExecutionPrompt,
buildScheduledTaskVerifiedHtmlUrls,
buildSimpleScheduledTaskReminderDelivery,
deliveryTextPromisesPublicHtml,
extractPublicHtmlPathsFromText,
extractScheduledTaskDeliveryText,
finalizeScheduledTaskPageDelivery,
formatScheduledTaskDeliveryMessage,
isSimpleScheduledTaskReminder,
looksLikeScheduledTaskNonDelivery,
reconcileStuckStaticPageDeliveryContracts,
resolveScheduledTaskDeliveryPollIntervalMs,
resolveScheduledTaskDeliveryRetryDelaysMs,
} from './scheduled-task-executor.mjs';
test('buildScheduledTaskExecutionPrompt includes task spec and automation marker', () => {
const message = buildScheduledTaskExecutionPrompt({
id: 'task-1',
title: '每日新闻页',
taskSpec: '搜索今日新闻并生成 HTML 页面',
recurrence: 'daily',
timezone: 'Asia/Shanghai',
});
const text = message.content[0].text;
assert.match(text, /scheduled-task-automation/);
assert.match(text, /每日新闻页/);
assert.match(text, /搜索今日新闻并生成 HTML 页面/);
assert.match(text, /Scheduled Automation/);
assert.match(text, /禁止调用 scheduled_task_create/);
});
test('isSimpleScheduledTaskReminder matches text-only reminder taskSpec', () => {
assert.equal(
isSimpleScheduledTaskReminder({
taskSpec: '提醒 icyxu:该吃药了,请按时服药,注意身体健康。',
}),
true,
);
assert.equal(
isSimpleScheduledTaskReminder({
taskSpec: '搜索今日新闻并生成 HTML 页面',
}),
false,
);
});
test('buildSimpleScheduledTaskReminderDelivery formats reminder body', () => {
assert.equal(
buildSimpleScheduledTaskReminderDelivery({
taskSpec: '提醒 icyxu:该吃药了,请按时服药,注意身体健康。',
}),
'icyxu,该吃药了,请按时服药,注意身体健康。',
);
});
test('looksLikeScheduledTaskNonDelivery detects task setup replies', () => {
assert.equal(
looksLikeScheduledTaskNonDelivery('定时自动任务已成功设置 ✅\n| 任务标题 | 每天上午10点提醒吃药 |'),
true,
);
assert.equal(
looksLikeScheduledTaskNonDelivery('任务已经存在且处于 active 状态,无需重复创建。'),
true,
);
});
test('looksLikeScheduledTaskNonDelivery detects clarification replies', () => {
assert.equal(
looksLikeScheduledTaskNonDelivery('请问 7月31日具体几点执行这个任务?'),
true,
);
assert.equal(
looksLikeScheduledTaskNonDelivery('页面已生成:https://example.com/news.html'),
false,
);
assert.equal(
looksLikeScheduledTaskNonDelivery(
'页面已生成:https://m.tkmind.cn/MindSpace/user-1/public/daily-news.html',
),
true,
);
assert.equal(
looksLikeScheduledTaskNonDelivery('好的', { readyPaths: ['public/news.html'] }),
false,
);
assert.equal(looksLikeScheduledTaskNonDelivery('验证成功'), false);
assert.equal(looksLikeScheduledTaskNonDelivery('已完成'), false);
assert.equal(looksLikeScheduledTaskNonDelivery('好的'), true);
});
test('extractPublicHtmlPathsFromText parses MindSpace public links', () => {
assert.deepEqual(
extractPublicHtmlPathsFromText(
'链接:https://m.tkmind.cn/MindSpace/u/public/daily-news-0816.html',
),
['public/daily-news-0816.html'],
);
});
test('deliveryTextPromisesPublicHtml detects page delivery replies', () => {
assert.equal(
deliveryTextPromisesPublicHtml('今日摘要:天气不错'),
false,
);
assert.equal(
deliveryTextPromisesPublicHtml('public/daily-news.html 已生成'),
true,
);
});
test('resolveScheduledTaskDeliveryPollIntervalMs reads env override', () => {
assert.equal(
resolveScheduledTaskDeliveryPollIntervalMs({
H5_SCHEDULED_TASK_DELIVERY_POLL_INTERVAL_MS: '7500',
}),
7500,
);
});
test('resolveScheduledTaskDeliveryRetryDelaysMs keeps backward-compatible shape', () => {
assert.deepEqual(
resolveScheduledTaskDeliveryRetryDelaysMs({
H5_SCHEDULED_TASK_DELIVERY_POLL_INTERVAL_MS: '100',
}),
[0, 100, 100, 100],
);
});
test('buildScheduledTaskVerifiedHtmlUrls maps ready paths to public urls', () => {
assert.deepEqual(
buildScheduledTaskVerifiedHtmlUrls('user-1', ['public/news.html'], {
publicBaseUrl: 'https://m.tkmind.cn',
}),
['https://m.tkmind.cn/MindSpace/user-1/public/news.html'],
);
});
test('finalizeScheduledTaskPageDelivery prepares and releases static contracts', async () => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), 'scheduled-task-finalize-'));
const publishDir = path.join(dir, 'MindSpace', 'user-1');
const relativePath = 'public/news.html';
await fs.mkdir(path.dirname(path.join(publishDir, relativePath)), { recursive: true });
await fs.writeFile(path.join(publishDir, relativePath), '<html></html>', 'utf8');
const calls = [];
const pool = {
async query(sql, params) {
calls.push({ sql, params });
if (sql.includes('FROM h5_page_delivery_contracts')) {
return [[{ workspace_relative_path: relativePath }]];
}
if (sql.includes('SELECT id, data_mode, status')) {
return [[{ id: 'c1', data_mode: 'static', status: 'preparing' }]];
}
if (sql.includes("SET status = 'ready'")) {
return [{ affectedRows: 1 }];
}
return [[]];
},
};
const readyPaths = await finalizeScheduledTaskPageDelivery({
pool,
userId: 'user-1',
sessionId: 'session-1',
messages: [],
publishDir,
deliveryText: 'public/news.html 已生成',
logger: { warn() {}, info() {} },
});
assert.deepEqual(readyPaths, [relativePath]);
assert.ok(calls.some((call) => call.sql.includes('INSERT INTO h5_page_delivery_contracts')));
});
test('finalizeScheduledTaskPageDelivery skips release when html file is missing', async () => {
const publishDir = path.join(await fs.mkdtemp(path.join(os.tmpdir(), 'scheduled-task-finalize-missing-')), 'MindSpace', 'user-1');
await fs.mkdir(publishDir, { recursive: true });
const pool = {
async query(sql) {
if (sql.includes('FROM h5_page_delivery_contracts')) {
return [[{ workspace_relative_path: 'public/news.html' }]];
}
if (sql.includes('SELECT id, data_mode, status')) {
return [[{ id: 'c1', data_mode: 'static', status: 'preparing' }]];
}
if (sql.includes("SET status = 'ready'")) {
throw new Error('should not mark ready without html file');
}
return [[]];
},
};
const readyPaths = await finalizeScheduledTaskPageDelivery({
pool,
userId: 'user-1',
sessionId: 'session-1',
messages: [],
publishDir,
deliveryText: 'public/news.html 已生成',
logger: { warn() {}, info() {} },
});
assert.deepEqual(readyPaths, []);
});
test('reconcileStuckStaticPageDeliveryContracts releases materialized static pages', async () => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), 'scheduled-task-'));
const userId = 'user-1';
const relativePath = 'public/news.html';
const filePath = path.join(dir, 'MindSpace', userId, relativePath);
await fs.mkdir(path.dirname(filePath), { recursive: true });
await fs.writeFile(filePath, '<html></html>', 'utf8');
const pool = {
async query(sql) {
if (sql.includes('FROM h5_page_delivery_contracts')) {
return [[{ user_id: userId, workspace_relative_path: relativePath }]];
}
if (sql.includes("SET status = 'ready'")) {
return [{ affectedRows: 1 }];
}
return [[]];
},
};
const released = await reconcileStuckStaticPageDeliveryContracts({
pool,
h5Root: dir,
logger: { info() {} },
});
assert.deepEqual(released, [{ userId, relativePath }]);
});
test('reconcileStuckStaticPageDeliveryContracts fails orphan contracts without html', async () => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), 'scheduled-task-orphan-'));
const userId = 'user-1';
const relativePath = 'public/missing.html';
const pool = {
async query(sql) {
if (sql.includes('FROM h5_page_delivery_contracts')) {
return [[{ user_id: userId, workspace_relative_path: relativePath }]];
}
if (sql.includes("SET status = 'failed'")) {
return [{ affectedRows: 1 }];
}
return [[]];
},
};
const released = await reconcileStuckStaticPageDeliveryContracts({
pool,
h5Root: dir,
logger: { info() {} },
});
assert.deepEqual(released, []);
});
test('extractScheduledTaskDeliveryText reads last assistant message', () => {
const text = extractScheduledTaskDeliveryText([
{ role: 'user', content: [{ type: 'text', text: 'hi' }] },
{ role: 'assistant', content: [{ type: 'text', text: '今日新闻页:https://example.com/news.html' }] },
], { title: '每日新闻页' });
assert.match(text, /https:\/\/example.com\/news.html/);
});
test('formatScheduledTaskDeliveryMessage wraps delivery body', () => {
const text = formatScheduledTaskDeliveryMessage(
{ title: '每日新闻页' },
'页面已生成:https://example.com/news.html',
);
assert.match(text, /定时任务完成:每日新闻页/);
assert.match(text, /页面已生成/);
});