Files
memind/scripts/test-cursor-help-e2e.mjs
T
john a15c4177de
Memind CI / Test, build, and release guards (push) Successful in 10m3s
test(cursor): add executor routing and help remediation scenarios
Add dry-run, e2e, and poem-page remediation scripts for cursor executor
and help escalation verification.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-27 09:33:51 +08:00

128 lines
4.1 KiB
JavaScript

#!/usr/bin/env node
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { setTimeout as sleep } from 'node:timers/promises';
import { createDbPool, migrateSchema } from '../db.mjs';
import {
HELP_ESCALATION_STATUS,
createHelpEscalationService,
isHelpEscalationIntent,
} from '../help-escalation.mjs';
import { processOneHelpEscalation } from '../cursor-help-worker.mjs';
const root = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
function loadEnvFile(filePath) {
if (!fs.existsSync(filePath)) return;
for (const line of fs.readFileSync(filePath, 'utf8').split('\n')) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith('#')) continue;
const eq = trimmed.indexOf('=');
if (eq < 0) continue;
const key = trimmed.slice(0, eq).trim();
const value = trimmed.slice(eq + 1).trim();
if (!process.env[key]) process.env[key] = value;
}
}
loadEnvFile(path.join(root, '.env'));
loadEnvFile(path.join(root, '.env.local'));
const args = process.argv.slice(2);
const enqueueOnly = args.includes('--enqueue-only');
const processLocally = args.includes('--process-locally');
const userIdArg = args.find((item) => item.startsWith('--user-id='))?.slice('--user-id='.length)?.trim() ?? '';
const waitMs = Number(
args.find((item) => item.startsWith('--wait-ms='))?.slice('--wait-ms='.length)
?? process.env.MEMIND_CURSOR_HELP_E2E_WAIT_MS
?? 10 * 60 * 1000,
);
const pool = createDbPool();
async function waitForEscalation(helpEscalationService, escalationId) {
const deadline = Date.now() + waitMs;
while (Date.now() < deadline) {
const current = await helpEscalationService.getById(escalationId);
if (
current?.status === HELP_ESCALATION_STATUS.SUCCEEDED
|| current?.status === HELP_ESCALATION_STATUS.FAILED
) {
return current;
}
console.log('waiting for worker...', {
id: escalationId,
status: current?.status ?? 'missing',
});
await sleep(2000);
}
throw new Error(`Timed out after ${waitMs}ms waiting for escalation ${escalationId}`);
}
try {
await migrateSchema(pool);
const helpEscalationService = createHelpEscalationService({ pool });
if (!helpEscalationService.enabled) {
console.error('MEMIND_CURSOR_HELP_ENABLED is not enabled');
process.exitCode = 1;
} else {
const sampleText = 'help 本机端到端测试:请检查 Portal /api/status 是否正常,并回复一行 JSON 结果。';
console.log('help intent:', isHelpEscalationIntent(sampleText));
let userId = userIdArg;
if (!userId) {
const [rows] = await pool.query('SELECT id, username FROM h5_users ORDER BY created_at ASC LIMIT 1');
userId = rows[0]?.id;
}
if (!userId) {
console.error('No h5_users row found for e2e test');
process.exitCode = 1;
} else {
const escalation = await helpEscalationService.enqueue({
userId,
channel: 'h5',
userText: sampleText,
context: {
origin: 'e2e-test',
requestId: `help-e2e-${Date.now()}`,
},
});
console.log('enqueued:', {
id: escalation.id,
userId: escalation.userId,
status: escalation.status,
});
if (!enqueueOnly) {
let completed = null;
if (processLocally) {
console.log('processing locally with agent CLI (portal worker should be disabled)...');
completed = await processOneHelpEscalation({
helpEscalationService,
logger: console,
});
} else {
console.log('waiting for portal/standalone cursor-help worker...');
completed = await waitForEscalation(helpEscalationService, escalation.id);
}
console.log('completed:', {
id: completed?.id ?? null,
status: completed?.status ?? null,
resultText: completed?.resultText ?? null,
errorMessage: completed?.errorMessage ?? null,
});
if (!completed || completed.status !== HELP_ESCALATION_STATUS.SUCCEEDED) {
process.exitCode = 1;
}
}
}
}
} finally {
await pool.end();
}