From c58a23d155dd8f2b1ac97a53e9a6c3c354ba27c4 Mon Sep 17 00:00:00 2001 From: john Date: Mon, 10 Aug 2026 22:41:29 +0800 Subject: [PATCH] fix(scheduled-task): improve live verify and short delivery acceptance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extend live verify wait budget to cover Agent execution timeout, use a deterministic smoke taskSpec, and accept concise successful replies like 「验证成功」 instead of treating them as non-delivery. Co-authored-by: Cursor --- scheduled-task-executor.mjs | 5 ++++- scheduled-task-executor.test.mjs | 3 +++ scripts/verify-scheduled-task-automation.mjs | 21 +++++++++++++++++--- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/scheduled-task-executor.mjs b/scheduled-task-executor.mjs index 90e0ba3..b35b932 100644 --- a/scheduled-task-executor.mjs +++ b/scheduled-task-executor.mjs @@ -94,7 +94,10 @@ export function looksLikeScheduledTaskNonDelivery(text, { readyPaths = [] } = {} if (/public\/[^\s]+\.html/i.test(normalized)) return false; if (/页面链接/u.test(normalized)) return false; if (/(?:已生成|已完成|交付).{0,24}(?:页面|链接|结果)/u.test(normalized)) return false; - return normalized.length < 40; + if (/^验证成功[。!!]?$/u.test(normalized)) return false; + if (/^(?:任务)?(?:已)?完成[。!!]?$/u.test(normalized)) return false; + if (/^【验证】/u.test(normalized) && normalized.length >= 6) return false; + return normalized.length < 12; } export async function finalizeScheduledTaskPageDelivery({ diff --git a/scheduled-task-executor.test.mjs b/scheduled-task-executor.test.mjs index 760949c..94bc4ee 100644 --- a/scheduled-task-executor.test.mjs +++ b/scheduled-task-executor.test.mjs @@ -36,6 +36,9 @@ test('looksLikeScheduledTaskNonDelivery detects clarification replies', () => { looksLikeScheduledTaskNonDelivery('好的', { readyPaths: ['public/news.html'] }), false, ); + assert.equal(looksLikeScheduledTaskNonDelivery('验证成功'), false); + assert.equal(looksLikeScheduledTaskNonDelivery('已完成'), false); + assert.equal(looksLikeScheduledTaskNonDelivery('好的'), true); }); test('extractScheduledTaskDeliveryText reads last assistant message', () => { diff --git a/scripts/verify-scheduled-task-automation.mjs b/scripts/verify-scheduled-task-automation.mjs index d4970a6..2c0f895 100644 --- a/scripts/verify-scheduled-task-automation.mjs +++ b/scripts/verify-scheduled-task-automation.mjs @@ -204,7 +204,7 @@ async function testLivePortalWorker(pool, userId, { dueSeconds }) { const created = await scheduledTaskService.createTask({ userId, title: `${TEST_TITLE_PREFIX}live_portal`, - taskSpec: '用三句话总结今天的热点新闻(验证脚本,回复文本即可,不要生成页面)', + taskSpec: '【验证】直接回复一行文字:验证成功。禁止追问、禁止生成页面、禁止调用任何工具。', recurrence: 'once', runAtLocal: formatRunAtLocal(runAtMs, tz), notifyChannel: 'web', @@ -212,10 +212,16 @@ async function testLivePortalWorker(pool, userId, { dueSeconds }) { }); pass('Live 任务已创建', `${waitSeconds}s 后执行,id=${created.id}`); - console.log(`\n等待 Portal worker 执行(最多 ${waitSeconds + 120}s)…`); + const executionTimeoutMs = Number( + process.env.H5_SCHEDULED_TASK_EXECUTION_TIMEOUT_MS + ?? process.env.VERIFY_SCHEDULED_TASK_EXECUTION_TIMEOUT_MS + ?? 180_000, + ); + const waitBudgetMs = waitSeconds * 1000 + executionTimeoutMs + 60_000; + console.log(`\n等待 Portal worker 执行(最多 ${Math.ceil(waitBudgetMs / 1000)}s,含 Agent 超时 ${Math.ceil(executionTimeoutMs / 1000)}s)…`); console.log('请确认 Portal 进程已开启 scheduled task worker(H5_SCHEDULED_TASK_WORKER_ENABLED=1,或未设置时 H5_REMINDER_WORKER_ENABLED=1)\n'); - const deadline = Date.now() + (waitSeconds + 120) * 1000; + const deadline = Date.now() + waitBudgetMs; let terminal = null; while (Date.now() < deadline) { const [rows] = await pool.query( @@ -223,6 +229,11 @@ async function testLivePortalWorker(pool, userId, { dueSeconds }) { [created.id], ); terminal = rows[0]; + if (!terminal) { + fail('Live Portal worker', `任务 ${created.id} 在数据库中消失`); + await cleanupTestRows(pool, userId); + return; + } if (terminal?.status === 'completed' || terminal?.status === 'failed') break; await new Promise((resolve) => setTimeout(resolve, 5000)); } @@ -231,6 +242,10 @@ async function testLivePortalWorker(pool, userId, { dueSeconds }) { pass('Live Portal worker', `任务 completed,updated_at=${terminal.updated_at}`); } else if (terminal?.status === 'failed') { fail('Live Portal worker', terminal.last_error ?? 'failed'); + } else if (terminal?.status === 'running') { + fail('Live Portal worker', `Agent 仍在执行中(status=running);可提高 H5_SCHEDULED_TASK_EXECUTION_TIMEOUT_MS 或检查 Goose 连通性`); + } else if (terminal?.status === 'active' && terminal?.last_error) { + fail('Live Portal worker', `已失败并重试调度:${terminal.last_error}`); } else { fail('Live Portal worker', `超时,最后 status=${terminal?.status ?? 'unknown'}`); }