feat: update xianyu web login and Hermes optimizer

This commit is contained in:
2026-05-06 20:36:19 +08:00
parent 6384156097
commit d5294a3f9b
15 changed files with 800 additions and 62 deletions
+54 -3
View File
@@ -5,7 +5,8 @@ import { genId, timestamp } from './utils.mjs';
import { checkLogin } from './login.mjs';
import { searchProducts } from './search.mjs';
import { coarseFilter, fineFilter } from './filter.mjs';
import { buildAnalysis } from './analyzer.mjs';
import { buildAnalysis, renderAnalysisMarkdown } from './analyzer.mjs';
import { sendNotifications } from './notifier.mjs';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const DATA_DIR = path.join(__dirname, '..', 'data');
@@ -36,6 +37,8 @@ export class TaskManager {
finePrompt: config.finePrompt || '',
maxPages: Math.max(1, Math.min(20, Number(config.maxPages || 3))),
maxItems: Math.max(1, Math.min(500, Number(config.maxItems || 60))),
autoAnalyze: config.autoAnalyze !== false,
autoNotify: config.autoNotify !== false,
schedule: {
enabled: !!scheduleEnabled,
intervalMinutes: Math.max(0, Number(scheduleIntervalMinutes || 0) || 0),
@@ -123,7 +126,7 @@ export class TaskManager {
async startTask(id, configUpdates = {}) {
const task = this.tasks.get(id);
if (!task || task.running) return;
if (!task || task.running) return null;
if (Object.keys(configUpdates || {}).length) {
const { reset, scheduled, ...patch } = configUpdates;
@@ -151,6 +154,7 @@ export class TaskManager {
try {
await this._runPipeline(task, emitLog, shouldStop);
if (!task.stopped) {
await this._runAutoAnalysis(task, emitLog);
task.stage = 'completed';
}
} catch (err) {
@@ -268,6 +272,52 @@ export class TaskManager {
return task;
}
async _runAutoAnalysis(task, emitLog) {
if (task.config?.autoAnalyze === false) {
emitLog('🦐 已关闭自动 Hermes 分析:可在详情页手动执行分析');
return null;
}
if (!task.products?.fineFiltered?.length) {
emitLog('🦐 没有细筛候选,跳过自动 Hermes 分析');
return null;
}
emitLog(`🦐 自动执行 Hermes 分析:${task.products.fineFiltered.length} 个候选`);
const analysis = this.analyzeTask(task.id, { limit: Number(task.config.maxItems || 50) });
if (!analysis?.summary) {
emitLog('⚠️ Hermes 分析未生成结果');
return null;
}
try {
const report = renderAnalysisMarkdown(this.getTaskFull(task.id), analysis.summary);
analysis.summary.reportPath = report.path;
this.setTaskAnalysis(task.id, analysis);
emitLog(`📝 Hermes 分析报告已生成:${report.path}`);
} catch (err) {
emitLog(`⚠️ Hermes 报告生成失败:${err.message}`);
}
if (task.config?.autoNotify !== false) {
try {
const notification = await sendNotifications(this.getTaskFull(task.id), analysis.summary);
if (notification?.skipped) {
emitLog(`🔕 自动通知跳过:${notification.reason || '未达到通知条件'}`);
} else if (notification?.ok) {
emitLog('📣 自动通知已发送');
} else {
const errors = (notification?.results || []).filter(r => !r.ok).map(r => `${r.name || r.id}: ${r.error}`).join('');
emitLog(`⚠️ 自动通知部分失败:${errors || '未知错误'}`);
}
} catch (err) {
emitLog(`⚠️ 自动通知失败:${err.message}`);
}
} else {
emitLog('🔕 已关闭自动通知');
}
return analysis;
}
getAllTasks() {
return [...this.tasks.values()].map(t => this._serialize(t));
}
@@ -370,7 +420,7 @@ export class TaskManager {
task.chatSessionsFull = [];
this._emit(task.id, 'task:chats', task.chatSessions);
this._persistToDisk();
emitLog(`🦐 已关闭联系卖家功能:保留 ${task.products.fineFiltered.length} 个候选商品,后续由 Hermes 读取 data/tasks.json 做深度分析报告`);
emitLog(`🦐 采集和本地预筛完成:保留 ${task.products.fineFiltered.length} 个候选,准备自动执行 Hermes 分析`);
emitLog('========== 采集流程结束 ==========');
}
@@ -547,6 +597,7 @@ export class TaskManager {
}
_startScheduler() {
if (process.env.XIANHU_DISABLE_SCHEDULER === '1') return;
this.schedulerTimer = setInterval(() => this._tickSchedules(), 30000);
}