Files
makemd/server/src/services/SelfHealingService.ts

107 lines
3.2 KiB
TypeScript
Raw Normal View History

import { AIService } from './AIService';
import { logger } from '../utils/logger';
import db from '../config/database';
export interface SelectorRepairResult {
success: boolean;
newSelector?: string;
confidence: number;
}
/**
* [CORE_AI_09] (Self-Healing Crawler Selectors)
* @description AI
*/
export class SelfHealingService {
private static readonly TABLE_NAME = 'cf_selector_repairs';
/**
*
*/
static async repairSelector(params: {
platform: string;
targetField: string;
oldSelector: string;
htmlContext: string;
}): Promise<SelectorRepairResult> {
logger.warn(`[SelfHealing] Repairing selector for ${params.platform}.${params.targetField}: ${params.oldSelector}`);
try {
// 1. 调用 AI 获取新选择器
const repairResult = await AIService.suggestNewSelector({
field: params.targetField,
oldSelector: params.oldSelector,
html: params.htmlContext
});
if (repairResult && repairResult.newSelector) {
// 2. 记录修复记录
await this.recordRepair({
platform: params.platform,
field: params.targetField,
old_selector: params.oldSelector,
new_selector: repairResult.newSelector,
confidence: repairResult.confidence,
status: 'pending_verification'
});
return {
success: true,
newSelector: repairResult.newSelector,
confidence: repairResult.confidence
};
}
return { success: false, confidence: 0 };
} catch (err: any) {
logger.error(`[SelfHealing] Repair failed: ${err.message}`);
return { success: false, confidence: 0 };
}
}
/**
*
*/
private static async recordRepair(data: any) {
await db(this.TABLE_NAME).insert({
...data,
created_at: new Date(),
updated_at: new Date()
});
}
/**
*
*/
static async getHealedSelector(platform: string, field: string): Promise<string | null> {
const record = await db(this.TABLE_NAME)
.where({ platform, field, status: 'verified' })
.orderBy('created_at', 'desc')
.first();
return record ? record.new_selector : null;
}
/**
*
*/
static async initTable() {
const exists = await db.schema.hasTable(this.TABLE_NAME);
if (!exists) {
logger.info(`📦 Creating ${this.TABLE_NAME} table...`);
await db.schema.createTable(this.TABLE_NAME, (table) => {
table.increments('id').primary();
table.string('platform', 32).notNullable();
table.string('field', 64).notNullable();
table.string('old_selector', 255).notNullable();
table.string('new_selector', 255).notNullable();
table.float('confidence').defaultTo(0);
table.string('status', 32).defaultTo('pending_verification'); // pending_verification, verified, failed
table.timestamps(true, true);
table.index(['platform', 'field']);
});
logger.info(`✅ Table ${this.TABLE_NAME} created`);
}
}
}