UNPKG

locatai-ts

Version:

Enterprise-grade AI-powered element locator for Selenium WebDriver - TypeScript implementation

115 lines 4.09 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.JsonFileLocatorStats = void 0; const path_1 = __importDefault(require("path")); const JsonFileHelpers_1 = require("./JsonFileHelpers"); /** * File-based implementation of ILocatorStats that tracks locator success rates */ class JsonFileLocatorStats { /** * Creates a new JSON file locator statistics tracker * @param root Optional root directory path */ constructor(root = process.cwd()) { this._gate = Promise.resolve(); this._stats = { version: 1, entries: [] }; this._cacheDir = path_1.default.join(root, 'LocatAICache'); this._filePath = path_1.default.join(this._cacheDir, 'locatai_stats.json'); this._init(); } /** * Initialize the stats by loading from disk */ async _init() { await (0, JsonFileHelpers_1.ensureDir)(this._cacheDir); this._stats = await (0, JsonFileHelpers_1.readJson)(this._filePath, { version: 1, entries: [] }); } /** * Execute a function with lock to prevent concurrent file access * @param work Function to execute * @returns Result of the function */ async _lock(work) { const prev = this._gate; let release; this._gate = new Promise(r => (release = r)); await prev; try { const result = await work(); await (0, JsonFileHelpers_1.writeJson)(this._filePath, this._stats); return result; } finally { release(); } } /** * @inheritdoc */ async recordAttempt(url, query, domHash, strategy, value, success) { return this._lock(async () => { let entry = this._stats.entries.find(e => e.url === url && e.query === query && e.dom === domHash); if (!entry) { entry = { url, query, dom: domHash, locators: [] }; this._stats.entries.push(entry); } let locator = entry.locators.find(l => l.strategy === strategy && l.value === value); if (!locator) { locator = { strategy, value, success: 0, failure: 0 }; entry.locators.push(locator); } success ? locator.success++ : locator.failure++; const attempts = locator.success + locator.failure; const rate = attempts === 0 ? 0 : locator.success / attempts; // Prune bad locators (those with >=3 attempts and <30% success rate) if (attempts >= 3 && rate < 0.30) { entry.locators = entry.locators.filter(l => l !== locator); } return rate; }); } /** * @inheritdoc */ async removeLocator(url, query, domHash, strategy, value) { await this._lock(async () => { const entry = this._stats.entries.find(e => e.url === url && e.query === query && e.dom === domHash); if (entry) { entry.locators = entry.locators.filter(l => !(l.strategy === strategy && l.value === value)); } }); } /** * @inheritdoc */ async getAll() { await this._gate; const result = []; for (const entry of this._stats.entries) { for (const locator of entry.locators) { const key = `${locator.strategy}=${locator.value}`; const total = locator.success + locator.failure; result.push({ locator: key, total: total, successes: locator.success }); } } return result; } /** * @inheritdoc */ async clear() { await this._lock(async () => { this._stats.entries = []; }); } } exports.JsonFileLocatorStats = JsonFileLocatorStats; //# sourceMappingURL=JsonFileLocatorStats.js.map