feat(help): add cursor help escalation worker and chat bridge
Introduce help escalation persistence, cursor help worker processing, optional OpenAI-compatible chat bridge, and page delivery remediation. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env node
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { createDbPool } from '../db.mjs';
|
||||
import {
|
||||
createHelpEscalationService,
|
||||
isHelpEscalationIntent,
|
||||
} from '../help-escalation.mjs';
|
||||
import {
|
||||
isCursorHelpWorkerEnabled,
|
||||
processOneHelpEscalation,
|
||||
startCursorHelpWorker,
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
||||
function parseArgs(argv) {
|
||||
const args = { once: false, status: false, help: false };
|
||||
for (const item of argv) {
|
||||
if (item === '--once') args.once = true;
|
||||
else if (item === '--status') args.status = true;
|
||||
else if (item === '--help' || item === '-h') args.help = true;
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
function printHelp() {
|
||||
console.log([
|
||||
'Usage:',
|
||||
' node scripts/cursor-help-worker.mjs [--once] [--status]',
|
||||
'',
|
||||
'Environment:',
|
||||
' MEMIND_CURSOR_HELP_ENABLED=1',
|
||||
' MEMIND_CURSOR_HELP_WORKER_ENABLED=1',
|
||||
' MEMIND_CURSOR_HELP_WORKSPACE=/Users/john/Project/Memind',
|
||||
' MEMIND_CURSOR_HELP_AGENT_BIN=~/.local/bin/agent',
|
||||
' MEMIND_CURSOR_HELP_POLL_MS=2000',
|
||||
].join('\n'));
|
||||
}
|
||||
|
||||
loadEnvFile(process.env.MEMIND_ENV_FILE || path.join(root, '.env'));
|
||||
loadEnvFile(path.join(root, '.env.local'));
|
||||
|
||||
const args = parseArgs(process.argv.slice(2));
|
||||
if (args.help) {
|
||||
printHelp();
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const pool = createDbPool();
|
||||
const helpEscalationService = createHelpEscalationService({ pool });
|
||||
|
||||
if (args.status) {
|
||||
const stats = await helpEscalationService.getQueueStats();
|
||||
console.log(JSON.stringify({
|
||||
ok: true,
|
||||
enabled: helpEscalationService.enabled,
|
||||
workerEnabled: isCursorHelpWorkerEnabled(),
|
||||
helpIntentSample: isHelpEscalationIntent('help 我的页面打不开'),
|
||||
stats,
|
||||
}, null, 2));
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (args.once) {
|
||||
const result = await processOneHelpEscalation({ helpEscalationService });
|
||||
console.log(JSON.stringify({ ok: true, processed: Boolean(result), result }, null, 2));
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const worker = startCursorHelpWorker({ pool });
|
||||
if (!worker.helpEscalationService?.enabled || !isCursorHelpWorkerEnabled()) {
|
||||
console.error('Cursor help worker is disabled. Set MEMIND_CURSOR_HELP_ENABLED=1 and MEMIND_CURSOR_HELP_WORKER_ENABLED=1');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
process.on('SIGINT', () => {
|
||||
worker.stop();
|
||||
process.exit(0);
|
||||
});
|
||||
process.on('SIGTERM', () => {
|
||||
worker.stop();
|
||||
process.exit(0);
|
||||
});
|
||||
Reference in New Issue
Block a user